Merge pull request #99119 from Fahien/fahien/raytracing-base

Vulkan raytracing plumbing
This commit is contained in:
Thaddeus Crews
2026-01-27 15:18:24 -06:00
28 changed files with 2998 additions and 114 deletions

View File

@@ -105,6 +105,8 @@ 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_BUILD_INPUT:
case RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ:
return false;
case RESOURCE_USAGE_COPY_TO:
case RESOURCE_USAGE_RESOLVE_TO:
@@ -114,6 +116,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 +176,12 @@ 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_BUILD_INPUT:
// Acceleration structure build inputs can be either storage buffers with vertices, indices, transforms, or
// other acceleration structures (BLAS)
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_COPY_READ_BIT | RDD::BARRIER_ACCESS_ACCELERATION_STRUCTURE_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 +205,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 +362,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;
@@ -568,6 +585,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 +780,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->width, trace_rays_instruction->height);
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 +1086,10 @@ 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_ACCELERATION_STRUCTURE_BUILD: {
const RecordedAccelerationStructureBuildCommand *as_build_command = reinterpret_cast<const RecordedAccelerationStructureBuildCommand *>(command);
driver->command_build_acceleration_structure(r_command_buffer, as_build_command->acceleration_structure, as_build_command->scratch_buffer);
} 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,6 +1113,10 @@ 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) {
// Avoid compute after draw workaround. Refer to the comment that enables this in the Vulkan driver for more information.
@@ -1313,6 +1403,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 +1425,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 +1438,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 +1623,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) {
@@ -1623,6 +1761,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 +1784,33 @@ void RenderingDeviceGraph::begin() {
#endif
}
void RenderingDeviceGraph::add_acceleration_structure_build(RDD::AccelerationStructureID p_acceleration_structure, RDD::BufferID p_scratch_buffer, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers) {
int32_t command_index;
RecordedAccelerationStructureBuildCommand *command = static_cast<RecordedAccelerationStructureBuildCommand *>(_allocate_command(sizeof(RecordedAccelerationStructureBuildCommand), command_index));
command->type = RecordedCommand::TYPE_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_ACCELERATION_STRUCTURE_BUILD_INPUT;
}
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 +1901,88 @@ 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(uint32_t p_width, uint32_t p_height) {
RaytracingListTraceRaysInstruction *instruction = reinterpret_cast<RaytracingListTraceRaysInstruction *>(_allocate_raytracing_list_instruction(sizeof(RaytracingListTraceRaysInstruction)));
instruction->type = RaytracingListInstruction::TYPE_TRACE_RAYS;
instruction->width = p_width;
instruction->height = p_height;
}
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)