feat: updated engine

This commit is contained in:
Sara Gerretsen 2026-07-10 17:04:34 +02:00
parent cbe99774ff
commit f4cf6b3999
6607 changed files with 910135 additions and 430025 deletions

View file

@ -105,6 +105,7 @@ bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ:
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ:
case RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ:
return false;
case RESOURCE_USAGE_COPY_TO:
case RESOURCE_USAGE_RESOLVE_TO:
@ -114,6 +115,7 @@ bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE:
case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE:
case RESOURCE_USAGE_GENERAL:
case RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE:
return true;
default:
DEV_ASSERT(false && "Invalid resource tracker usage.");
@ -173,6 +175,8 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage
return RDD::BARRIER_ACCESS_UNIFORM_READ_BIT;
case RESOURCE_USAGE_INDIRECT_BUFFER_READ:
return RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT;
case RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ:
return RDD::BARRIER_ACCESS_ACCELERATION_STRUCTURE_READ_BIT;
case RESOURCE_USAGE_STORAGE_BUFFER_READ:
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
case RESOURCE_USAGE_TEXTURE_BUFFER_READ:
@ -196,6 +200,8 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage
return RDD::BARRIER_ACCESS_FRAGMENT_DENSITY_MAP_ATTACHMENT_READ_BIT;
case RESOURCE_USAGE_GENERAL:
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_MEMORY_READ_BIT | RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT);
case RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE:
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_ACCELERATION_STRUCTURE_READ_BIT | RDD::BARRIER_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT);
default:
DEV_ASSERT(false && "Invalid usage.");
return RDD::BarrierAccessBits(0);
@ -351,6 +357,12 @@ void RenderingDeviceGraph::_check_discardable_attachment_dependency(ResourceTrac
}
}
RenderingDeviceGraph::RaytracingListInstruction *RenderingDeviceGraph::_allocate_raytracing_list_instruction(uint32_t p_instruction_size) {
uint32_t raytracing_list_data_offset = raytracing_instruction_list.data.size();
raytracing_instruction_list.data.resize(raytracing_list_data_offset + p_instruction_size);
return reinterpret_cast<RaytracingListInstruction *>(&raytracing_instruction_list.data[raytracing_list_data_offset]);
}
void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_trackers, ResourceUsage *p_resource_usages, uint32_t p_resource_count, int32_t p_command_index, RecordedCommand *r_command) {
// Assign the next stages derived from the stages the command requires first.
r_command->next_stages = r_command->self_stages;
@ -394,6 +406,13 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
resource_tracker->reset_if_outdated(tracking_frame);
resource_tracker->command_index = p_command_index;
resource_tracker->usage_index = i;
}
for (uint32_t i = 0; i < p_resource_count; i++) {
ResourceTracker *resource_tracker = p_resource_trackers[i];
const RDD::TextureSubresourceRange &subresources = resource_tracker->texture_subresources;
const Rect2i resource_tracker_rect(subresources.base_mipmap, subresources.base_layer, subresources.mipmap_count, subresources.layer_count);
Rect2i search_tracker_rect = resource_tracker_rect;
@ -406,6 +425,15 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
// This resource depends on a parent resource.
resource_tracker->parent->reset_if_outdated(tracking_frame);
// Quit early if the parent is already in this command.
if (resource_tracker->parent->command_index == p_command_index) {
DEV_ASSERT(resource_tracker->parent->usage_index != UINT32_MAX);
ERR_FAIL_COND_MSG(p_resource_usages[resource_tracker->parent->usage_index] != new_resource_usage, "Using a full texture and its slices at the same time with different usages is not allowed.");
continue;
}
if (resource_tracker->texture_slice_command_index != p_command_index) {
// Indicate this slice has been used by this command.
resource_tracker->texture_slice_command_index = p_command_index;
@ -568,6 +596,11 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
// Memory barriers are pushed regardless of buffer barriers being used or not.
r_command->memory_barrier.src_access = r_command->memory_barrier.src_access | resource_tracker->usage_access;
r_command->memory_barrier.dst_access = r_command->memory_barrier.dst_access | new_usage_access;
} else if (resource_tracker->acceleration_structure_driver_id.id != 0) {
// Make sure the acceleration structure has been built before accessing it from raytracing shaders.
_add_acceleration_structure_barrier_to_command(resource_tracker->acceleration_structure_driver_id, resource_tracker->usage_access, new_usage_access, command_acceleration_structure_barriers, r_command->acceleration_structure_barrier_index, r_command->acceleration_structure_barrier_count);
r_command->memory_barrier.src_access = r_command->memory_barrier.src_access | resource_tracker->usage_access;
r_command->memory_barrier.dst_access = r_command->memory_barrier.dst_access | new_usage_access;
} else {
DEV_ASSERT(false && "Resource tracker does not contain a valid buffer or texture ID.");
}
@ -758,6 +791,66 @@ void RenderingDeviceGraph::_add_buffer_barrier_to_command(RDD::BufferID p_buffer
}
#endif
void RenderingDeviceGraph::_add_acceleration_structure_barrier_to_command(RDD::AccelerationStructureID p_acceleration_structure_id, BitField<RDD::BarrierAccessBits> p_src_access, BitField<RDD::BarrierAccessBits> p_dst_access, LocalVector<RDD::AccelerationStructureBarrier> &r_barrier_vector, int32_t &r_barrier_index, int32_t &r_barrier_count) {
if (!driver_honors_barriers) {
return;
}
if (r_barrier_index < 0) {
r_barrier_index = r_barrier_vector.size();
}
RDD::AccelerationStructureBarrier accel_barrier;
accel_barrier.acceleration_structure = p_acceleration_structure_id;
accel_barrier.src_access = p_src_access;
accel_barrier.dst_access = p_dst_access;
accel_barrier.offset = 0;
accel_barrier.size = RDD::BUFFER_WHOLE_SIZE;
r_barrier_vector.push_back(accel_barrier);
r_barrier_count++;
}
void RenderingDeviceGraph::_run_raytracing_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) {
uint32_t instruction_data_cursor = 0;
while (instruction_data_cursor < p_instruction_data_size) {
DEV_ASSERT((instruction_data_cursor + sizeof(RaytracingListInstruction)) <= p_instruction_data_size);
const RaytracingListInstruction *instruction = reinterpret_cast<const RaytracingListInstruction *>(&p_instruction_data[instruction_data_cursor]);
switch (instruction->type) {
case RaytracingListInstruction::TYPE_BIND_PIPELINE: {
const RaytracingListBindPipelineInstruction *bind_pipeline_instruction = reinterpret_cast<const RaytracingListBindPipelineInstruction *>(instruction);
driver->command_bind_raytracing_pipeline(p_command_buffer, bind_pipeline_instruction->pipeline);
instruction_data_cursor += sizeof(RaytracingListBindPipelineInstruction);
} break;
case RaytracingListInstruction::TYPE_BIND_UNIFORM_SET: {
const RaytracingListBindUniformSetInstruction *bind_uniform_set_instruction = reinterpret_cast<const RaytracingListBindUniformSetInstruction *>(instruction);
driver->command_bind_raytracing_uniform_set(p_command_buffer, bind_uniform_set_instruction->uniform_set, bind_uniform_set_instruction->shader, bind_uniform_set_instruction->set_index);
instruction_data_cursor += sizeof(RaytracingListBindUniformSetInstruction);
} break;
case RaytracingListInstruction::TYPE_TRACE_RAYS: {
const RaytracingListTraceRaysInstruction *trace_rays_instruction = reinterpret_cast<const RaytracingListTraceRaysInstruction *>(instruction);
driver->command_trace_rays(p_command_buffer, trace_rays_instruction->raygen_sbt, trace_rays_instruction->miss_sbt, trace_rays_instruction->hit_sbt, trace_rays_instruction->width, trace_rays_instruction->height, trace_rays_instruction->depth);
instruction_data_cursor += sizeof(RaytracingListTraceRaysInstruction);
} break;
case RaytracingListInstruction::TYPE_SET_PUSH_CONSTANT: {
const RaytracingListSetPushConstantInstruction *set_push_constant_instruction = reinterpret_cast<const RaytracingListSetPushConstantInstruction *>(instruction);
const VectorView push_constant_data_view(reinterpret_cast<const uint32_t *>(set_push_constant_instruction->data()), set_push_constant_instruction->size / sizeof(uint32_t));
driver->command_bind_push_constants(p_command_buffer, set_push_constant_instruction->shader, 0, push_constant_data_view);
instruction_data_cursor += sizeof(RaytracingListSetPushConstantInstruction);
instruction_data_cursor += set_push_constant_instruction->size;
} break;
case RaytracingListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE: {
const RaytracingListUniformSetPrepareForUseInstruction *uniform_set_prepare_for_use_instruction = reinterpret_cast<const RaytracingListUniformSetPrepareForUseInstruction *>(instruction);
driver->command_uniform_set_prepare_for_use(p_command_buffer, uniform_set_prepare_for_use_instruction->uniform_set, uniform_set_prepare_for_use_instruction->shader, uniform_set_prepare_for_use_instruction->set_index);
instruction_data_cursor += sizeof(RaytracingListUniformSetPrepareForUseInstruction);
} break;
default:
DEV_ASSERT(false && "Unknown raytracing list instruction type.");
return;
}
}
}
void RenderingDeviceGraph::_run_compute_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) {
uint32_t instruction_data_cursor = 0;
while (instruction_data_cursor < p_instruction_data_size) {
@ -1004,6 +1097,14 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC
_run_label_command_change(r_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level);
switch (command->type) {
case RecordedCommand::TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_BUILD: {
const RecordedBottomLevelAccelerationStructureBuildCommand *blas_build_command = reinterpret_cast<const RecordedBottomLevelAccelerationStructureBuildCommand *>(command);
driver->command_build_blas(r_command_buffer, blas_build_command->acceleration_structure, blas_build_command->scratch_buffer);
} break;
case RecordedCommand::TYPE_TOP_LEVEL_ACCELERATION_STRUCTURE_BUILD: {
const RecordedTopLevelAccelerationStructureBuildCommand *tlas_build_command = reinterpret_cast<const RecordedTopLevelAccelerationStructureBuildCommand *>(command);
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);
} break;
case RecordedCommand::TYPE_BUFFER_CLEAR: {
const RecordedBufferClearCommand *buffer_clear_command = reinterpret_cast<const RecordedBufferClearCommand *>(command);
driver->command_clear_buffer(r_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size);
@ -1027,8 +1128,12 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC
const RecordedDriverCallbackCommand *driver_callback_command = reinterpret_cast<const RecordedDriverCallbackCommand *>(command);
driver_callback_command->callback(driver, r_command_buffer, driver_callback_command->userdata);
} break;
case RecordedCommand::TYPE_RAYTRACING_LIST: {
const RecordedRaytracingListCommand *raytracing_list_command = reinterpret_cast<const RecordedRaytracingListCommand *>(command);
_run_raytracing_list_command(r_command_buffer, raytracing_list_command->instruction_data(), raytracing_list_command->instruction_data_size);
} break;
case RecordedCommand::TYPE_COMPUTE_LIST: {
if (device.workarounds.avoid_compute_after_draw && workarounds_state.draw_list_found) {
if (driver_workarounds.avoid_compute_after_draw && workarounds_state.draw_list_found) {
// Avoid compute after draw workaround. Refer to the comment that enables this in the Vulkan driver for more information.
workarounds_state.draw_list_found = false;
@ -1052,7 +1157,7 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC
_run_compute_list_command(r_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size);
} break;
case RecordedCommand::TYPE_DRAW_LIST: {
if (device.workarounds.avoid_compute_after_draw) {
if (driver_workarounds.avoid_compute_after_draw) {
// Indicate that a draw list was encountered for the workaround.
workarounds_state.draw_list_found = true;
}
@ -1313,6 +1418,12 @@ void RenderingDeviceGraph::_group_barriers_for_render_commands(RDD::CommandBuffe
barrier_group.buffer_barriers.push_back(recorded_barrier);
}
#endif
// Gather acceleration structure barriers.
for (int32_t j = 0; j < command->acceleration_structure_barrier_count; j++) {
const RDD::AccelerationStructureBarrier &recorded_barrier = command_acceleration_structure_barriers[command->acceleration_structure_barrier_index + j];
barrier_group.acceleration_structure_barriers.push_back(recorded_barrier);
}
}
if (p_full_memory_barrier) {
@ -1329,7 +1440,8 @@ void RenderingDeviceGraph::_group_barriers_for_render_commands(RDD::CommandBuffe
#else
const bool are_buffer_barriers_empty = true;
#endif
if (is_memory_barrier_empty && are_texture_barriers_empty && are_buffer_barriers_empty) {
const bool are_acceleration_structure_barriers_empty = barrier_group.acceleration_structure_barriers.is_empty();
if (is_memory_barrier_empty && are_texture_barriers_empty && are_buffer_barriers_empty && are_acceleration_structure_barriers_empty) {
// Commands don't require synchronization.
return;
}
@ -1341,12 +1453,13 @@ void RenderingDeviceGraph::_group_barriers_for_render_commands(RDD::CommandBuffe
#else
const VectorView<RDD::BufferBarrier> buffer_barriers = VectorView<RDD::BufferBarrier>();
#endif
const VectorView<RDD::AccelerationStructureBarrier> acceleration_structure_barriers = !are_acceleration_structure_barriers_empty ? barrier_group.acceleration_structure_barriers : VectorView<RDD::AccelerationStructureBarrier>();
driver->command_pipeline_barrier(p_command_buffer, barrier_group.src_stages, barrier_group.dst_stages, memory_barriers, buffer_barriers, texture_barriers);
driver->command_pipeline_barrier(p_command_buffer, barrier_group.src_stages, barrier_group.dst_stages, memory_barriers, buffer_barriers, texture_barriers, acceleration_structure_barriers);
bool separate_texture_barriers = !barrier_group.normalization_barriers.is_empty() && !barrier_group.transition_barriers.is_empty();
if (separate_texture_barriers) {
driver->command_pipeline_barrier(p_command_buffer, barrier_group.src_stages, barrier_group.dst_stages, VectorView<RDD::MemoryAccessBarrier>(), VectorView<RDD::BufferBarrier>(), barrier_group.transition_barriers);
driver->command_pipeline_barrier(p_command_buffer, barrier_group.src_stages, barrier_group.dst_stages, VectorView<RDD::MemoryAccessBarrier>(), VectorView<RDD::BufferBarrier>(), barrier_group.transition_barriers, VectorView<RDD::AccelerationStructureBarrier>());
}
}
@ -1525,6 +1638,46 @@ void RenderingDeviceGraph::_print_draw_list(const uint8_t *p_instruction_data, u
}
}
void RenderingDeviceGraph::_print_raytracing_list(const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) {
uint32_t instruction_data_cursor = 0;
while (instruction_data_cursor < p_instruction_data_size) {
DEV_ASSERT((instruction_data_cursor + sizeof(RaytracingListInstruction)) <= p_instruction_data_size);
const RaytracingListInstruction *instruction = reinterpret_cast<const RaytracingListInstruction *>(&p_instruction_data[instruction_data_cursor]);
switch (instruction->type) {
case RaytracingListInstruction::TYPE_BIND_PIPELINE: {
const RaytracingListBindPipelineInstruction *bind_pipeline_instruction = reinterpret_cast<const RaytracingListBindPipelineInstruction *>(instruction);
print_line("\tBIND PIPELINE ID", itos(bind_pipeline_instruction->pipeline.id));
instruction_data_cursor += sizeof(RaytracingListBindPipelineInstruction);
} break;
case RaytracingListInstruction::TYPE_BIND_UNIFORM_SET: {
const RaytracingListBindUniformSetInstruction *bind_uniform_set_instruction = reinterpret_cast<const RaytracingListBindUniformSetInstruction *>(instruction);
print_line("\tBIND UNIFORM SET ID", itos(bind_uniform_set_instruction->uniform_set.id), "SHADER ID", itos(bind_uniform_set_instruction->shader.id));
instruction_data_cursor += sizeof(RaytracingListBindUniformSetInstruction);
} break;
case RaytracingListInstruction::TYPE_SET_PUSH_CONSTANT: {
const RaytracingListSetPushConstantInstruction *set_push_constant_instruction = reinterpret_cast<const RaytracingListSetPushConstantInstruction *>(instruction);
print_line("\tSET PUSH CONSTANT SIZE", set_push_constant_instruction->size);
instruction_data_cursor += sizeof(RaytracingListSetPushConstantInstruction);
instruction_data_cursor += set_push_constant_instruction->size;
} break;
case RaytracingListInstruction::TYPE_TRACE_RAYS: {
const RaytracingListTraceRaysInstruction *trace_rays_instruction = reinterpret_cast<const RaytracingListTraceRaysInstruction *>(instruction);
print_line("\tTRACE RAYS WIDTH", itos(trace_rays_instruction->width), "HEIGHT", itos(trace_rays_instruction->height));
instruction_data_cursor += sizeof(RaytracingListTraceRaysInstruction);
} break;
case RaytracingListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE: {
const RaytracingListUniformSetPrepareForUseInstruction *uniform_set_prepare_for_use_instruction = reinterpret_cast<const RaytracingListUniformSetPrepareForUseInstruction *>(instruction);
print_line("\tUNIFORM SET PREPARE FOR USE ID", itos(uniform_set_prepare_for_use_instruction->uniform_set.id), "SHADER ID", itos(uniform_set_prepare_for_use_instruction->shader.id), "INDEX", itos(uniform_set_prepare_for_use_instruction->set_index));
instruction_data_cursor += sizeof(RaytracingListUniformSetPrepareForUseInstruction);
} break;
default:
DEV_ASSERT(false && "Unknown raytracing list instruction type.");
return;
}
}
}
void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) {
uint32_t instruction_data_cursor = 0;
while (instruction_data_cursor < p_instruction_data_size) {
@ -1575,13 +1728,13 @@ void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data
}
}
void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Device p_device, RenderPassCreationFunction p_render_pass_creation_function, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
void RenderingDeviceGraph::initialize(RDD *p_driver, RenderPassCreationFunction p_render_pass_creation_function, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
DEV_ASSERT(p_driver != nullptr);
DEV_ASSERT(p_render_pass_creation_function != nullptr);
DEV_ASSERT(p_frame_count > 0);
driver = p_driver;
device = p_device;
driver_workarounds = p_driver->get_driver_workarounds();
render_pass_creation_function = p_render_pass_creation_function;
frames.resize(p_frame_count);
@ -1623,6 +1776,7 @@ void RenderingDeviceGraph::begin() {
command_normalization_barriers.clear();
command_transition_barriers.clear();
command_buffer_barriers.clear();
command_acceleration_structure_barriers.clear();
command_label_chars.clear();
command_label_colors.clear();
command_label_offsets.clear();
@ -1645,6 +1799,63 @@ void RenderingDeviceGraph::begin() {
#endif
}
void RenderingDeviceGraph::add_blas_build(RDD::AccelerationStructureID p_acceleration_structure, RDD::BufferID p_scratch_buffer, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers) {
int32_t command_index;
RecordedBottomLevelAccelerationStructureBuildCommand *command = static_cast<RecordedBottomLevelAccelerationStructureBuildCommand *>(_allocate_command(sizeof(RecordedBottomLevelAccelerationStructureBuildCommand), command_index));
command->type = RecordedCommand::TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_BUILD;
command->self_stages = RDD::PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT;
command->acceleration_structure = p_acceleration_structure;
command->scratch_buffer = p_scratch_buffer;
thread_local LocalVector<ResourceTracker *> trackers;
thread_local LocalVector<ResourceUsage> usages;
// Sources and destination.
uint32_t resource_count = p_src_trackers.size() + 1;
trackers.resize(resource_count);
usages.resize(resource_count);
for (uint32_t i = 0; i < p_src_trackers.size(); ++i) {
trackers[i] = p_src_trackers[i];
usages[i] = RESOURCE_USAGE_STORAGE_BUFFER_READ;
}
trackers[resource_count - 1] = p_dst_tracker;
usages[resource_count - 1] = RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE;
_add_command_to_graph(trackers.ptr(), usages.ptr(), usages.size(), command_index, command);
}
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) {
int32_t command_index;
RecordedTopLevelAccelerationStructureBuildCommand *command = static_cast<RecordedTopLevelAccelerationStructureBuildCommand *>(_allocate_command(sizeof(RecordedTopLevelAccelerationStructureBuildCommand), command_index));
command->type = RecordedCommand::TYPE_TOP_LEVEL_ACCELERATION_STRUCTURE_BUILD;
command->self_stages = RDD::PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT;
command->acceleration_structure = p_acceleration_structure;
command->scratch_buffer = p_scratch_buffer;
command->instance_buffer = p_instance_buffer;
command->instance_offset = p_instance_offset;
command->instance_count = p_instance_count;
thread_local LocalVector<ResourceTracker *> trackers;
thread_local LocalVector<ResourceUsage> usages;
// Sources and destination.
uint32_t resource_count = p_src_trackers.size() + 1;
trackers.resize(resource_count);
usages.resize(resource_count);
for (uint32_t i = 0; i < p_src_trackers.size(); ++i) {
trackers[i] = p_src_trackers[i];
usages[i] = RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ;
}
trackers[resource_count - 1] = p_dst_tracker;
usages[resource_count - 1] = RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE;
_add_command_to_graph(trackers.ptr(), usages.ptr(), usages.size(), command_index, command);
}
void RenderingDeviceGraph::add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size) {
DEV_ASSERT(p_dst_tracker != nullptr);
@ -1735,6 +1946,92 @@ void RenderingDeviceGraph::add_driver_callback(RDD::DriverCallback p_callback, v
_add_command_to_graph((ResourceTracker **)p_trackers.ptr(), (ResourceUsage *)p_usages.ptr(), p_trackers.size(), command_index, command);
}
void RenderingDeviceGraph::add_raytracing_list_begin() {
raytracing_instruction_list.clear();
raytracing_instruction_list.index++;
}
void RenderingDeviceGraph::add_raytracing_list_bind_pipeline(RDD::RaytracingPipelineID p_pipeline) {
RaytracingListBindPipelineInstruction *instruction = reinterpret_cast<RaytracingListBindPipelineInstruction *>(_allocate_raytracing_list_instruction(sizeof(RaytracingListBindPipelineInstruction)));
instruction->type = RaytracingListInstruction::TYPE_BIND_PIPELINE;
instruction->pipeline = p_pipeline;
raytracing_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_RAY_TRACING_SHADER_BIT);
}
void RenderingDeviceGraph::add_raytracing_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index) {
RaytracingListBindUniformSetInstruction *instruction = reinterpret_cast<RaytracingListBindUniformSetInstruction *>(_allocate_raytracing_list_instruction(sizeof(RaytracingListBindUniformSetInstruction)));
instruction->type = RaytracingListInstruction::TYPE_BIND_UNIFORM_SET;
instruction->shader = p_shader;
instruction->uniform_set = p_uniform_set;
instruction->set_index = set_index;
}
void RenderingDeviceGraph::add_raytracing_list_set_push_constant(RDD::ShaderID p_shader, const void *p_data, uint32_t p_data_size) {
uint32_t instruction_size = sizeof(RaytracingListSetPushConstantInstruction) + p_data_size;
RaytracingListSetPushConstantInstruction *instruction = reinterpret_cast<RaytracingListSetPushConstantInstruction *>(_allocate_raytracing_list_instruction(instruction_size));
instruction->type = RaytracingListInstruction::TYPE_SET_PUSH_CONSTANT;
instruction->size = p_data_size;
instruction->shader = p_shader;
memcpy(instruction->data(), p_data, p_data_size);
}
void RenderingDeviceGraph::add_raytracing_list_trace_rays(const RDD::ShaderBindingTable &p_raygen_sbt, const RDD::ShaderBindingTable &p_miss_sbt, const RDD::ShaderBindingTable &p_hit_sbt, uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
RaytracingListTraceRaysInstruction *instruction = reinterpret_cast<RaytracingListTraceRaysInstruction *>(_allocate_raytracing_list_instruction(sizeof(RaytracingListTraceRaysInstruction)));
instruction->type = RaytracingListInstruction::TYPE_TRACE_RAYS;
instruction->raygen_sbt = p_raygen_sbt;
instruction->miss_sbt = p_miss_sbt;
instruction->hit_sbt = p_hit_sbt;
instruction->width = p_width;
instruction->height = p_height;
instruction->depth = p_depth;
}
void RenderingDeviceGraph::add_raytracing_list_uniform_set_prepare_for_use(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index) {
RaytracingListUniformSetPrepareForUseInstruction *instruction = reinterpret_cast<RaytracingListUniformSetPrepareForUseInstruction *>(_allocate_raytracing_list_instruction(sizeof(RaytracingListUniformSetPrepareForUseInstruction)));
instruction->type = RaytracingListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE;
instruction->shader = p_shader;
instruction->uniform_set = p_uniform_set;
instruction->set_index = set_index;
}
void RenderingDeviceGraph::add_raytracing_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage) {
DEV_ASSERT(p_tracker != nullptr);
p_tracker->reset_if_outdated(tracking_frame);
if (p_tracker->raytracing_list_index != raytracing_instruction_list.index) {
raytracing_instruction_list.command_trackers.push_back(p_tracker);
raytracing_instruction_list.command_tracker_usages.push_back(p_usage);
p_tracker->raytracing_list_index = raytracing_instruction_list.index;
p_tracker->raytracing_list_usage = p_usage;
}
#ifdef DEV_ENABLED
else if (p_tracker->raytracing_list_usage != p_usage) {
ERR_FAIL_MSG(vformat("Tracker can't have more than one type of usage in the same raytracing list. Raytracing list usage is %d and the requested usage is %d.", p_tracker->raytracing_list_usage, p_usage));
}
#endif
}
void RenderingDeviceGraph::add_raytracing_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages) {
DEV_ASSERT(p_trackers.size() == p_usages.size());
for (uint32_t i = 0; i < p_trackers.size(); i++) {
add_raytracing_list_usage(p_trackers[i], p_usages[i]);
}
}
void RenderingDeviceGraph::add_raytracing_list_end() {
int32_t command_index;
uint32_t instruction_data_size = raytracing_instruction_list.data.size();
uint32_t command_size = sizeof(RecordedRaytracingListCommand) + instruction_data_size;
RecordedRaytracingListCommand *command = static_cast<RecordedRaytracingListCommand *>(_allocate_command(command_size, command_index));
command->type = RecordedCommand::TYPE_RAYTRACING_LIST;
command->self_stages = raytracing_instruction_list.stages;
command->instruction_data_size = instruction_data_size;
memcpy(command->instruction_data(), raytracing_instruction_list.data.ptr(), instruction_data_size);
_add_command_to_graph(raytracing_instruction_list.command_trackers.ptr(), raytracing_instruction_list.command_tracker_usages.ptr(), raytracing_instruction_list.command_trackers.size(), command_index, command);
}
void RenderingDeviceGraph::add_compute_list_begin(RDD::BreadcrumbMarker p_phase, uint32_t p_breadcrumb_data) {
compute_instruction_list.clear();
#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
@ -2362,13 +2659,16 @@ void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RD
}
// Batch buffer, texture, draw lists and compute operations together.
const uint32_t PriorityTable[RecordedCommand::TYPE_MAX] = {
const uint32_t PriorityTable[] = {
0, // TYPE_NONE
6, // TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_BUILD
6, // TYPE_TOP_LEVEL_ACCELERATION_STRUCTURE_BUILD
1, // TYPE_BUFFER_CLEAR
1, // TYPE_BUFFER_COPY
1, // TYPE_BUFFER_GET_DATA
1, // TYPE_BUFFER_UPDATE
4, // TYPE_COMPUTE_LIST
7, // TYPE_RAYTRACING_LIST
3, // TYPE_DRAW_LIST
2, // TYPE_TEXTURE_CLEAR_COLOR
2, // TYPE_TEXTURE_CLEAR_DEPTH_STENCIL
@ -2379,6 +2679,7 @@ void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RD
2, // TYPE_CAPTURE_TIMESTAMP
5, // TYPE_DRIVER_CALLBACK
};
static_assert(std_size(PriorityTable) == RecordedCommand::TYPE_MAX, "PriorityTable must have one entry per RecordedCommand::Type");
commands_sorted.clear();
commands_sorted.resize(command_count);
@ -2418,7 +2719,7 @@ void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RD
int32_t current_label_level = -1;
_run_label_command_change(r_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level);
if (device.workarounds.avoid_compute_after_draw) {
if (driver_workarounds.avoid_compute_after_draw) {
// Reset the state of the workaround.
workarounds_state.draw_list_found = false;
}