raytracing: Initial Vulkan support
- Vulkan implementations in `RenderingDeviceDriverVulkan`. - Raytracing instruction list in `RenderingDeviceGraph`. - Functions to create acceleration structures and raytracing pipelines in `RenderingDevice`. - Raygen, Miss, and ClosestHit shader stages support. - GDScript bindings. - Update classes documentation. - Unimplemented placeholders for Metal and D3D12. - Build acceleration structure command. - Expose a shader preprocessor define. - Align build scratch address. - Create STB after creating the pipeline. - Separate acceleration structure barriers. - Use transforms in TLAS instances. - AnyHit and Intersection stages. - Optionally set acceleration structure build input buffer usage. - Introduce instances buffer. - Move scratch buffers to RenderingDevice. - Rename AccelerationStructureGeometryBits. - Use regular buffer creation and free routines for scratch buffer. - Store trackers in acceleration structures. - Bump Shader SPIR-V version to 1.4 - Add Position attribute location in blas_create. - Encapsulate MoltenVK check in preprocessor macro. - Split SUPPORTS_RAYTRACING for pipeline and query.
This commit is contained in:
parent
66b9c7251e
commit
27e4f24800
28 changed files with 2998 additions and 114 deletions
|
|
@ -216,6 +216,238 @@ RID RenderingDevice::shader_create_from_spirv(const Vector<ShaderStageSPIRVData>
|
|||
return shader_create_from_bytecode(bytecode);
|
||||
}
|
||||
|
||||
/********************************/
|
||||
/**** ACCELERATION STRUCTURE ****/
|
||||
/********************************/
|
||||
|
||||
RID RenderingDevice::blas_create(RID p_vertex_array, RID p_index_array, BitField<AccelerationStructureGeometryBits> p_geometry_bits, uint32_t p_position_attribute_location) {
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE) && !has_feature(SUPPORTS_RAY_QUERY), RID(), "The current rendering device has neither raytracing pipeline nor ray query support.");
|
||||
|
||||
VertexArray *vertex_array = vertex_array_owner.get_or_null(p_vertex_array);
|
||||
ERR_FAIL_NULL_V(vertex_array, RID());
|
||||
|
||||
uint32_t position_binding = p_position_attribute_location;
|
||||
RDD::VertexFormatID vertex_format;
|
||||
|
||||
if (vertex_array->description != INVALID_ID) {
|
||||
ERR_FAIL_COND_V(!vertex_formats.has(vertex_array->description), RID());
|
||||
const VertexDescriptionCache &vd_cache = vertex_formats[vertex_array->description];
|
||||
vertex_format = vd_cache.driver_id;
|
||||
|
||||
const VertexAttribute *position_attribute = nullptr;
|
||||
for (int i = 0; i < vd_cache.vertex_formats.size(); i++) {
|
||||
const VertexAttribute &attr = vd_cache.vertex_formats[i];
|
||||
if (attr.location == p_position_attribute_location) {
|
||||
position_attribute = &attr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ERR_FAIL_NULL_V_MSG(position_attribute, RID(), vformat("Vertex array is missing a position attribute at location %u.", p_position_attribute_location));
|
||||
ERR_FAIL_COND_V_MSG(position_attribute->frequency != VERTEX_FREQUENCY_VERTEX, RID(), vformat("Position attribute at location %u must use vertex frequency.", p_position_attribute_location));
|
||||
|
||||
if (position_attribute->binding != UINT32_MAX) {
|
||||
position_binding = position_attribute->binding;
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(position_binding >= (uint32_t)vertex_array->buffers.size(), RID(), vformat("Vertex array is missing a buffer for binding %u.", position_binding));
|
||||
RDD::BufferID vertex_buffer = vertex_array->buffers[position_binding];
|
||||
uint64_t vertex_offset = vertex_array->offsets[position_binding];
|
||||
|
||||
// Indices are optional.
|
||||
IndexArray *index_array = index_array_owner.get_or_null(p_index_array);
|
||||
RDD::BufferID index_buffer = RDD::BufferID();
|
||||
IndexBufferFormat index_format = IndexBufferFormat::INDEX_BUFFER_FORMAT_UINT32;
|
||||
uint32_t index_offset_bytes = 0;
|
||||
uint32_t index_count = 0;
|
||||
if (index_array) {
|
||||
index_buffer = index_array->driver_id;
|
||||
index_format = index_array->format;
|
||||
index_offset_bytes = index_array->offset * (index_array->format == INDEX_BUFFER_FORMAT_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
|
||||
index_count = index_array->indices;
|
||||
}
|
||||
|
||||
AccelerationStructure acceleration_structure;
|
||||
acceleration_structure.type = RDD::ACCELERATION_STRUCTURE_TYPE_BLAS;
|
||||
|
||||
BitField<RDD::AccelerationStructureGeometryBits> geometry_bits = 0;
|
||||
if (p_geometry_bits.has_flag(ACCELERATION_STRUCTURE_GEOMETRY_OPAQUE)) {
|
||||
geometry_bits.set_flag(RDD::ACCELERATION_STRUCTURE_GEOMETRY_OPAQUE);
|
||||
}
|
||||
if (p_geometry_bits.has_flag(ACCELERATION_STRUCTURE_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION)) {
|
||||
geometry_bits.set_flag(RDD::ACCELERATION_STRUCTURE_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION);
|
||||
}
|
||||
|
||||
acceleration_structure.driver_id = driver->blas_create(vertex_buffer, vertex_offset, vertex_format, vertex_array->vertex_count, p_position_attribute_location, index_buffer, index_format, index_offset_bytes, index_count, geometry_bits);
|
||||
ERR_FAIL_COND_V_MSG(!acceleration_structure.driver_id, RID(), "Failed to create BLAS.");
|
||||
acceleration_structure.vertex_array = p_vertex_array;
|
||||
acceleration_structure.index_array = p_index_array;
|
||||
|
||||
acceleration_structure.draw_tracker = RDG::resource_tracker_create();
|
||||
acceleration_structure.draw_tracker->acceleration_structure_driver_id = acceleration_structure.driver_id;
|
||||
// Assume we are going to build this acceleration structure
|
||||
acceleration_structure.draw_tracker->usage = RDG::RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE;
|
||||
|
||||
for (int i = 0; i < vertex_array->draw_trackers.size(); i++) {
|
||||
acceleration_structure.draw_trackers.push_back(vertex_array->draw_trackers[i]);
|
||||
}
|
||||
_check_transfer_worker_vertex_array(vertex_array);
|
||||
|
||||
if (index_array && index_array->draw_tracker) {
|
||||
acceleration_structure.draw_trackers.push_back(index_array->draw_tracker);
|
||||
}
|
||||
_check_transfer_worker_index_array(index_array);
|
||||
|
||||
RID id = acceleration_structure_owner.make_rid(acceleration_structure);
|
||||
#ifdef DEV_ENABLED
|
||||
set_resource_name(id, "RID:" + itos(id.get_id()));
|
||||
#endif
|
||||
return id;
|
||||
}
|
||||
|
||||
BitField<RDD::BufferUsageBits> RenderingDevice::_creation_to_usage_bits(BitField<RD::BufferCreationBits> p_creation_bits) {
|
||||
BitField<RDD::BufferUsageBits> usage = 0;
|
||||
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_AS_STORAGE_BIT)) {
|
||||
usage.set_flag(RDD::BUFFER_USAGE_STORAGE_BIT);
|
||||
}
|
||||
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_BUFFER_DEVICE_ADDRESS), 0,
|
||||
"The GPU doesn't support buffer address flag.");
|
||||
#endif
|
||||
usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
|
||||
}
|
||||
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT)) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE) && !has_feature(SUPPORTS_RAY_QUERY), 0,
|
||||
"The GPU doesn't support acceleration structure build input flag.");
|
||||
#endif
|
||||
usage.set_flag(RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT);
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
RID RenderingDevice::tlas_instances_buffer_create(uint32_t p_instance_count, BitField<BufferCreationBits> p_creation_bits) {
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE) && !has_feature(SUPPORTS_RAY_QUERY), RID(), "The current rendering device has neither raytracing pipeline nor ray query support.");
|
||||
ERR_FAIL_COND_V(p_instance_count == 0, RID());
|
||||
|
||||
uint32_t instances_buffer_size_bytes = driver->tlas_instances_buffer_get_size_bytes(p_instance_count);
|
||||
|
||||
InstancesBuffer instances_buffer;
|
||||
instances_buffer.instance_count = p_instance_count;
|
||||
instances_buffer.buffer.size = instances_buffer_size_bytes;
|
||||
instances_buffer.buffer.usage = _creation_to_usage_bits(p_creation_bits) | RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT | RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT;
|
||||
instances_buffer.buffer.driver_id = driver->buffer_create(instances_buffer.buffer.size, instances_buffer.buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_CPU, frames_drawn);
|
||||
ERR_FAIL_COND_V_MSG(!instances_buffer.buffer.driver_id, RID(), "Failed to create instances buffer.");
|
||||
|
||||
_THREAD_SAFE_LOCK_
|
||||
buffer_memory += instances_buffer.buffer.size;
|
||||
_THREAD_SAFE_UNLOCK_
|
||||
|
||||
RID id = instances_buffer_owner.make_rid(instances_buffer);
|
||||
#ifdef DEV_ENABLED
|
||||
set_resource_name(id, "RID:" + itos(id.get_id()));
|
||||
#endif
|
||||
return id;
|
||||
}
|
||||
|
||||
void RenderingDevice::tlas_instances_buffer_fill(RID p_instances_buffer, const Vector<RID> &p_blases, VectorView<Transform3D> p_transforms) {
|
||||
ERR_FAIL_COND_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE) && !has_feature(SUPPORTS_RAY_QUERY), "The current rendering device has neither raytracing pipeline nor ray query support.");
|
||||
|
||||
InstancesBuffer *instances_buffer = instances_buffer_owner.get_or_null(p_instances_buffer);
|
||||
ERR_FAIL_NULL_MSG(instances_buffer, "Instances buffer input is not valid.");
|
||||
|
||||
uint32_t blases_count = p_blases.size();
|
||||
ERR_FAIL_COND_MSG(blases_count != instances_buffer->instance_count, "The number of blases is not equal to the instance count of the instances buffer.");
|
||||
ERR_FAIL_COND_MSG(blases_count != p_transforms.size(), "Blases and transforms vectors must have the same size.");
|
||||
|
||||
thread_local LocalVector<RDD::AccelerationStructureID> blases;
|
||||
blases.resize(blases_count);
|
||||
|
||||
for (uint32_t i = 0; i < blases_count; i++) {
|
||||
const AccelerationStructure *blas = acceleration_structure_owner.get_or_null(p_blases[i]);
|
||||
ERR_FAIL_NULL_MSG(blas, "BLAS input is not valid.");
|
||||
ERR_FAIL_COND_MSG(blas->type != RDD::ACCELERATION_STRUCTURE_TYPE_BLAS, "Acceleration structure input is not a BLAS.");
|
||||
blases[i] = blas->driver_id;
|
||||
}
|
||||
|
||||
instances_buffer->blases = p_blases;
|
||||
|
||||
driver->tlas_instances_buffer_fill(instances_buffer->buffer.driver_id, blases, p_transforms);
|
||||
}
|
||||
|
||||
RID RenderingDevice::tlas_create(RID p_instances_buffer) {
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE) && !has_feature(SUPPORTS_RAY_QUERY), RID(), "The current rendering device has neither raytracing pipeline nor ray query support.");
|
||||
|
||||
const InstancesBuffer *instances_buffer = instances_buffer_owner.get_or_null(p_instances_buffer);
|
||||
ERR_FAIL_NULL_V_MSG(instances_buffer, RID(), "Instances buffer input is not valid.");
|
||||
|
||||
AccelerationStructure acceleration_structure;
|
||||
acceleration_structure.type = RDD::ACCELERATION_STRUCTURE_TYPE_TLAS;
|
||||
acceleration_structure.driver_id = driver->tlas_create(instances_buffer->buffer.driver_id);
|
||||
ERR_FAIL_COND_V_MSG(!acceleration_structure.driver_id, RID(), "Failed to create TLAS.");
|
||||
acceleration_structure.instances_buffer = p_instances_buffer;
|
||||
|
||||
acceleration_structure.draw_tracker = RDG::resource_tracker_create();
|
||||
acceleration_structure.draw_tracker->acceleration_structure_driver_id = acceleration_structure.driver_id;
|
||||
// Assume we are going to build this acceleration structure
|
||||
acceleration_structure.draw_tracker->usage = RDG::RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE;
|
||||
|
||||
for (Vector<RID>::ConstIterator itr = instances_buffer->blases.begin(); itr != instances_buffer->blases.end(); ++itr) {
|
||||
const AccelerationStructure *blas = acceleration_structure_owner.get_or_null(*itr);
|
||||
ERR_FAIL_NULL_V_MSG(blas, RID(), "BLAS input is not valid.");
|
||||
if (blas->draw_tracker) {
|
||||
acceleration_structure.draw_trackers.push_back(blas->draw_tracker);
|
||||
}
|
||||
}
|
||||
|
||||
RID id = acceleration_structure_owner.make_rid(acceleration_structure);
|
||||
#ifdef DEV_ENABLED
|
||||
set_resource_name(id, "RID:" + itos(id.get_id()));
|
||||
#endif
|
||||
return id;
|
||||
}
|
||||
|
||||
Error RenderingDevice::acceleration_structure_build(RID p_acceleration_structure) {
|
||||
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
|
||||
"Building acceleration structures is forbidden during creation of a draw list.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
|
||||
"Building acceleration structures is forbidden during creation of a compute list.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, ERR_INVALID_PARAMETER,
|
||||
"Building acceleration structures is forbidden during creation of a raytracing list.");
|
||||
|
||||
AccelerationStructure *accel = acceleration_structure_owner.get_or_null(p_acceleration_structure);
|
||||
ERR_FAIL_NULL_V_MSG(accel, ERR_INVALID_PARAMETER, "Acceleration structure argument is not valid.");
|
||||
|
||||
uint64_t scratch_size = driver->acceleration_structure_get_scratch_size_bytes(accel->driver_id);
|
||||
|
||||
const Buffer *scratch_buffer = storage_buffer_owner.get_or_null(accel->scratch_buffer);
|
||||
if (scratch_buffer && driver->buffer_get_allocation_size(scratch_buffer->driver_id) < scratch_size) {
|
||||
scratch_buffer = nullptr;
|
||||
free_rid(accel->scratch_buffer);
|
||||
accel->scratch_buffer = RID();
|
||||
}
|
||||
if (accel->scratch_buffer == RID()) {
|
||||
accel->scratch_buffer = storage_buffer_create(scratch_size, { nullptr, 0 }, RDD::BUFFER_USAGE_STORAGE_BIT | RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
|
||||
ERR_FAIL_COND_V(accel->scratch_buffer == RID(), ERR_CANT_CREATE);
|
||||
}
|
||||
|
||||
if (scratch_buffer == nullptr) {
|
||||
scratch_buffer = storage_buffer_owner.get_or_null(accel->scratch_buffer);
|
||||
ERR_FAIL_NULL_V_MSG(scratch_buffer, ERR_CANT_CREATE, "Scratch buffer is not valid.");
|
||||
}
|
||||
|
||||
draw_graph.add_acceleration_structure_build(accel->driver_id, scratch_buffer->driver_id, accel->draw_tracker, accel->draw_trackers);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/**** BUFFER MANAGEMENT ****/
|
||||
/***************************/
|
||||
|
|
@ -233,6 +465,8 @@ RenderingDevice::Buffer *RenderingDevice::_get_buffer_from_owner(RID p_buffer) {
|
|||
//buffer = texture_buffer_owner.get_or_null(p_buffer)->buffer;
|
||||
} else if (storage_buffer_owner.owns(p_buffer)) {
|
||||
buffer = storage_buffer_owner.get_or_null(p_buffer);
|
||||
} else if (instances_buffer_owner.owns(p_buffer)) {
|
||||
buffer = &instances_buffer_owner.get_or_null(p_buffer)->buffer;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
|
@ -426,9 +660,11 @@ Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t
|
|||
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
|
||||
"Copying buffers is forbidden during creation of a draw list");
|
||||
"Copying buffers is forbidden during creation of a draw list.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
|
||||
"Copying buffers is forbidden during creation of a compute list");
|
||||
"Copying buffers is forbidden during creation of a compute list.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, ERR_INVALID_PARAMETER,
|
||||
"Copying buffers is forbidden during creation of a raytracing list.");
|
||||
|
||||
Buffer *src_buffer = _get_buffer_from_owner(p_src_buffer);
|
||||
if (!src_buffer) {
|
||||
|
|
@ -469,9 +705,11 @@ Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p
|
|||
copy_bytes_count += p_size;
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active && !p_skip_check, ERR_INVALID_PARAMETER,
|
||||
"Updating buffers is forbidden during creation of a draw list");
|
||||
"Updating buffers is forbidden during creation of a draw list.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active && !p_skip_check, ERR_INVALID_PARAMETER,
|
||||
"Updating buffers is forbidden during creation of a compute list");
|
||||
"Updating buffers is forbidden during creation of a compute list.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active && !p_skip_check, ERR_INVALID_PARAMETER,
|
||||
"Updating buffers is forbidden during creation of a raytracing list.");
|
||||
|
||||
Buffer *buffer = _get_buffer_from_owner(p_buffer);
|
||||
ERR_FAIL_NULL_V_MSG(buffer, ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type.");
|
||||
|
|
@ -557,9 +795,11 @@ Error RenderingDevice::driver_callback_add(RDD::DriverCallback p_callback, void
|
|||
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
|
||||
"Driver callback is forbidden during creation of a draw list");
|
||||
"Driver callback is forbidden during creation of a draw list.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
|
||||
"Driver callback is forbidden during creation of a compute list");
|
||||
"Driver callback is forbidden during creation of a compute list.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, ERR_INVALID_PARAMETER,
|
||||
"Driver callback is forbidden during creation of a raytracing list.");
|
||||
|
||||
thread_local LocalVector<RDG::ResourceTracker *> trackers;
|
||||
thread_local LocalVector<RDG::ResourceUsage> usages;
|
||||
|
|
@ -628,11 +868,13 @@ Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_
|
|||
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
|
||||
|
||||
ERR_FAIL_COND_V_MSG((p_size % 4) != 0, ERR_INVALID_PARAMETER,
|
||||
"Size must be a multiple of four");
|
||||
"Size must be a multiple of four.");
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
|
||||
"Updating buffers in is forbidden during creation of a draw list");
|
||||
"Updating buffers in is forbidden during creation of a draw list.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
|
||||
"Updating buffers is forbidden during creation of a compute list");
|
||||
"Updating buffers is forbidden during creation of a compute list.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, ERR_INVALID_PARAMETER,
|
||||
"Updating buffers is forbidden during creation of a raytracing list.");
|
||||
|
||||
Buffer *buffer = _get_buffer_from_owner(p_buffer);
|
||||
if (!buffer) {
|
||||
|
|
@ -840,6 +1082,14 @@ RID RenderingDevice::storage_buffer_create(uint32_t p_size_bytes, Span<uint8_t>
|
|||
|
||||
buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
|
||||
}
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT)) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE) && !has_feature(SUPPORTS_RAY_QUERY), RID(),
|
||||
"The GPU doesn't support acceleration structure build input flag.");
|
||||
#endif
|
||||
buffer.usage.set_flag(RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT);
|
||||
}
|
||||
|
||||
buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU, frames_drawn);
|
||||
ERR_FAIL_COND_V(!buffer.driver_id, RID());
|
||||
|
||||
|
|
@ -1528,7 +1778,7 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
|
|||
tb.subresources.mipmap_count = texture->mipmaps;
|
||||
tb.subresources.base_layer = p_layer;
|
||||
tb.subresources.layer_count = 1;
|
||||
driver->command_pipeline_barrier(transfer_worker->command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_COPY_BIT, {}, {}, tb);
|
||||
driver->command_pipeline_barrier(transfer_worker->command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_COPY_BIT, {}, {}, tb, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1614,7 +1864,9 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
|
|||
Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data) {
|
||||
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active || compute_list.active, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a draw or compute list");
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a draw list.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a compute list.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a raytracing list.");
|
||||
|
||||
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_NULL_V(texture, ERR_INVALID_PARAMETER);
|
||||
|
|
@ -3187,6 +3439,9 @@ RID RenderingDevice::vertex_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p
|
|||
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
|
||||
buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
|
||||
}
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT)) {
|
||||
buffer.usage.set_flag(RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT);
|
||||
}
|
||||
buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU, frames_drawn);
|
||||
ERR_FAIL_COND_V(!buffer.driver_id, RID());
|
||||
|
||||
|
|
@ -3389,9 +3644,15 @@ RID RenderingDevice::index_buffer_create(uint32_t p_index_count, IndexBufferForm
|
|||
#endif
|
||||
index_buffer.size = size_bytes;
|
||||
index_buffer.usage = (RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_INDEX_BIT);
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_AS_STORAGE_BIT)) {
|
||||
index_buffer.usage.set_flag(RDD::BUFFER_USAGE_STORAGE_BIT);
|
||||
}
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
|
||||
index_buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
|
||||
}
|
||||
if (p_creation_bits.has_flag(BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT)) {
|
||||
index_buffer.usage.set_flag(RDD::BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT);
|
||||
}
|
||||
index_buffer.driver_id = driver->buffer_create(index_buffer.size, index_buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU, frames_drawn);
|
||||
ERR_FAIL_COND_V(!index_buffer.driver_id, RID());
|
||||
|
||||
|
|
@ -3584,6 +3845,13 @@ RID RenderingDevice::shader_create_from_bytecode_with_samplers(const Vector<uint
|
|||
case SHADER_STAGE_COMPUTE:
|
||||
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
break;
|
||||
case SHADER_STAGE_RAYGEN:
|
||||
case SHADER_STAGE_ANY_HIT:
|
||||
case SHADER_STAGE_CLOSEST_HIT:
|
||||
case SHADER_STAGE_MISS:
|
||||
case SHADER_STAGE_INTERSECTION:
|
||||
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_RAY_TRACING_SHADER_BIT);
|
||||
break;
|
||||
default:
|
||||
DEV_ASSERT(false && "Unknown shader stage.");
|
||||
break;
|
||||
|
|
@ -4039,7 +4307,7 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
|
|||
_check_transfer_worker_buffer(buffer);
|
||||
} break;
|
||||
case UNIFORM_TYPE_INPUT_ATTACHMENT: {
|
||||
ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for compute shader (this is not allowed).");
|
||||
ERR_FAIL_COND_V_MSG(shader->pipeline_type != PIPELINE_TYPE_RASTERIZATION, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for non-render shader (this is not allowed).");
|
||||
|
||||
if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
|
||||
if (set_uniform.length > 1) {
|
||||
|
|
@ -4065,6 +4333,22 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
|
|||
_check_transfer_worker_texture(texture);
|
||||
}
|
||||
} break;
|
||||
case UNIFORM_TYPE_ACCELERATION_STRUCTURE: {
|
||||
ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
|
||||
"Acceleration structure supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
|
||||
|
||||
RID accel_id = uniform.get_id(0);
|
||||
AccelerationStructure *accel = acceleration_structure_owner.get_or_null(accel_id);
|
||||
ERR_FAIL_NULL_V_MSG(accel, RID(), "Acceleration Structure supplied (binding: " + itos(uniform.binding) + ") is invalid.");
|
||||
|
||||
if (accel->draw_tracker != nullptr) {
|
||||
draw_trackers.push_back(accel->draw_tracker);
|
||||
// Acceleration structure is never going to be writable from raytracing shaders
|
||||
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ);
|
||||
}
|
||||
|
||||
driver_uniform.ids.push_back(accel->driver_id);
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
|
@ -4129,7 +4413,8 @@ RID RenderingDevice::render_pipeline_create(RID p_shader, FramebufferFormatID p_
|
|||
// Needs a shader.
|
||||
Shader *shader = shader_owner.get_or_null(p_shader);
|
||||
ERR_FAIL_NULL_V(shader, RID());
|
||||
ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "Compute shaders can't be used in render pipelines");
|
||||
ERR_FAIL_COND_V_MSG(shader->pipeline_type != PIPELINE_TYPE_RASTERIZATION, RID(),
|
||||
"Only render shaders can be used in render pipelines");
|
||||
|
||||
// Validate pre-raster shader. One of stages must be vertex shader or mesh shader (not implemented yet).
|
||||
ERR_FAIL_COND_V_MSG(!shader->stage_bits.has_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT), RID(), "Pre-raster shader (vertex shader) is not provided for pipeline creation.");
|
||||
|
|
@ -4322,7 +4607,7 @@ RID RenderingDevice::compute_pipeline_create(RID p_shader, const Vector<Pipeline
|
|||
shader = shader_owner.get_or_null(p_shader);
|
||||
ERR_FAIL_NULL_V(shader, RID());
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!shader->is_compute, RID(),
|
||||
ERR_FAIL_COND_V_MSG(shader->pipeline_type != PIPELINE_TYPE_COMPUTE, RID(),
|
||||
"Non-compute shaders can't be used in compute pipelines");
|
||||
}
|
||||
|
||||
|
|
@ -4375,6 +4660,57 @@ bool RenderingDevice::compute_pipeline_is_valid(RID p_pipeline) {
|
|||
return compute_pipeline_owner.owns(p_pipeline);
|
||||
}
|
||||
|
||||
RID RenderingDevice::raytracing_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
// Needs a shader.
|
||||
Shader *shader = shader_owner.get_or_null(p_shader);
|
||||
ERR_FAIL_NULL_V(shader, RID());
|
||||
|
||||
ERR_FAIL_COND_V_MSG(shader->pipeline_type != PIPELINE_TYPE_RAYTRACING, RID(),
|
||||
"Only raytracing shaders can be used in raytracing pipelines");
|
||||
|
||||
for (int i = 0; i < shader->specialization_constants.size(); i++) {
|
||||
const ShaderSpecializationConstant &sc = shader->specialization_constants[i];
|
||||
for (int j = 0; j < p_specialization_constants.size(); j++) {
|
||||
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
|
||||
if (psc.constant_id == sc.constant_id) {
|
||||
ERR_FAIL_COND_V_MSG(psc.type != sc.type, RID(), "Specialization constant provided for id (" + itos(sc.constant_id) + ") is of the wrong type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RaytracingPipeline pipeline;
|
||||
pipeline.driver_id = driver->raytracing_pipeline_create(shader->driver_id, p_specialization_constants);
|
||||
ERR_FAIL_COND_V(!pipeline.driver_id, RID());
|
||||
|
||||
if (pipeline_cache_enabled) {
|
||||
update_pipeline_cache();
|
||||
}
|
||||
|
||||
pipeline.shader = p_shader;
|
||||
pipeline.shader_driver_id = shader->driver_id;
|
||||
pipeline.shader_layout_hash = shader->layout_hash;
|
||||
pipeline.set_formats = shader->set_formats;
|
||||
pipeline.push_constant_size = shader->push_constant_size;
|
||||
|
||||
// Create ID to associate with this pipeline.
|
||||
RID id = raytracing_pipeline_owner.make_rid(pipeline);
|
||||
#ifdef DEV_ENABLED
|
||||
set_resource_name(id, "RID:" + itos(id.get_id()));
|
||||
#endif
|
||||
// Now add all the dependencies.
|
||||
_add_dependency(id, p_shader);
|
||||
return id;
|
||||
}
|
||||
|
||||
bool RenderingDevice::raytracing_pipeline_is_valid(RID p_pipeline) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
return raytracing_pipeline_owner.owns(p_pipeline);
|
||||
}
|
||||
|
||||
/****************/
|
||||
/**** SCREEN ****/
|
||||
/****************/
|
||||
|
|
@ -4520,6 +4856,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS
|
|||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, INVALID_ID, "Only one draw list can be active at the same time.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one draw/compute list can be active at the same time.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, INVALID_ID, "Only one draw/raytracing list can be active at the same time.");
|
||||
|
||||
RenderingContextDriver::SurfaceID surface = context->surface_get_from_window(p_screen);
|
||||
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator sc_it = screen_swap_chains.find(p_screen);
|
||||
|
|
@ -5366,6 +5703,236 @@ void RenderingDevice::draw_list_end() {
|
|||
draw_list_bound_textures.clear();
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/**** RAYTRACING LISTS ****/
|
||||
/**************************/
|
||||
|
||||
RenderingDevice::RaytracingListID RenderingDevice::raytracing_list_begin() {
|
||||
ERR_RENDER_THREAD_GUARD_V(INVALID_ID);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_RAYTRACING_PIPELINE), INVALID_ID, "The current rendering device has no raytracing pipeline support.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(draw_list.active, INVALID_ID, "Only one draw/raytracing list can be active at the same time.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one compute/raytracing list can be active at the same time.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, INVALID_ID, "Only one raytracing list can be active at the same time.");
|
||||
|
||||
raytracing_list.active = true;
|
||||
|
||||
draw_graph.add_raytracing_list_begin();
|
||||
|
||||
return ID_TYPE_RAYTRACING_LIST;
|
||||
}
|
||||
|
||||
void RenderingDevice::raytracing_list_bind_raytracing_pipeline(RaytracingListID p_list, RID p_raytracing_pipeline) {
|
||||
ERR_RENDER_THREAD_GUARD();
|
||||
|
||||
ERR_FAIL_COND(p_list != ID_TYPE_RAYTRACING_LIST);
|
||||
ERR_FAIL_COND(!raytracing_list.active);
|
||||
|
||||
const RaytracingPipeline *pipeline = raytracing_pipeline_owner.get_or_null(p_raytracing_pipeline);
|
||||
ERR_FAIL_NULL(pipeline);
|
||||
|
||||
if (p_raytracing_pipeline == raytracing_list.state.pipeline) {
|
||||
return; // Redundant state, return.
|
||||
}
|
||||
|
||||
raytracing_list.state.pipeline = p_raytracing_pipeline;
|
||||
raytracing_list.state.pipeline_driver_id = pipeline->driver_id;
|
||||
|
||||
draw_graph.add_raytracing_list_bind_pipeline(pipeline->driver_id);
|
||||
|
||||
if (raytracing_list.state.pipeline_shader != pipeline->shader) {
|
||||
// Shader changed, so descriptor sets may become incompatible.
|
||||
|
||||
uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline.
|
||||
raytracing_list.state.set_count = MAX(raytracing_list.state.set_count, pcount);
|
||||
const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats.
|
||||
|
||||
uint32_t first_invalid_set = UINT32_MAX; // All valid by default.
|
||||
switch (driver->api_trait_get(RDD::API_TRAIT_SHADER_CHANGE_INVALIDATION)) {
|
||||
case RDD::SHADER_CHANGE_INVALIDATION_ALL_BOUND_UNIFORM_SETS: {
|
||||
first_invalid_set = 0;
|
||||
} break;
|
||||
case RDD::SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE: {
|
||||
for (uint32_t i = 0; i < pcount; i++) {
|
||||
if (raytracing_list.state.sets[i].pipeline_expected_format != pformats[i]) {
|
||||
first_invalid_set = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case RDD::SHADER_CHANGE_INVALIDATION_ALL_OR_NONE_ACCORDING_TO_LAYOUT_HASH: {
|
||||
if (raytracing_list.state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) {
|
||||
first_invalid_set = 0;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pcount; i++) {
|
||||
raytracing_list.state.sets[i].bound = raytracing_list.state.sets[i].bound && i < first_invalid_set;
|
||||
raytracing_list.state.sets[i].pipeline_expected_format = pformats[i];
|
||||
}
|
||||
|
||||
for (uint32_t i = pcount; i < raytracing_list.state.set_count; i++) {
|
||||
// Unbind the ones above (not used) if exist.
|
||||
raytracing_list.state.sets[i].bound = false;
|
||||
}
|
||||
|
||||
raytracing_list.state.set_count = pcount; // Update set count.
|
||||
|
||||
if (pipeline->push_constant_size) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
raytracing_list.validation.pipeline_push_constant_supplied = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
raytracing_list.state.pipeline_shader = pipeline->shader;
|
||||
raytracing_list.state.pipeline_shader_driver_id = pipeline->shader_driver_id;
|
||||
raytracing_list.state.pipeline_shader_layout_hash = pipeline->shader_layout_hash;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
// Update raytracing pass pipeline info.
|
||||
raytracing_list.validation.pipeline_active = true;
|
||||
raytracing_list.validation.pipeline_push_constant_size = pipeline->push_constant_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderingDevice::raytracing_list_bind_uniform_set(RaytracingListID p_list, RID p_uniform_set, uint32_t p_index) {
|
||||
ERR_RENDER_THREAD_GUARD();
|
||||
|
||||
ERR_FAIL_COND(p_list != ID_TYPE_RAYTRACING_LIST);
|
||||
ERR_FAIL_COND(!raytracing_list.active);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_MSG(p_index >= driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS) || p_index >= MAX_UNIFORM_SETS,
|
||||
"Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS)) + ").");
|
||||
#endif
|
||||
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_uniform_set);
|
||||
ERR_FAIL_NULL(uniform_set);
|
||||
|
||||
if (p_index > raytracing_list.state.set_count) {
|
||||
raytracing_list.state.set_count = p_index;
|
||||
}
|
||||
|
||||
raytracing_list.state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer.
|
||||
raytracing_list.state.sets[p_index].bound = false; // Needs rebind.
|
||||
raytracing_list.state.sets[p_index].uniform_set_format = uniform_set->format;
|
||||
raytracing_list.state.sets[p_index].uniform_set = p_uniform_set;
|
||||
}
|
||||
|
||||
void RenderingDevice::raytracing_list_set_push_constant(RaytracingListID p_list, const void *p_data, uint32_t p_data_size) {
|
||||
ERR_RENDER_THREAD_GUARD();
|
||||
|
||||
ERR_FAIL_COND(p_list != ID_TYPE_RAYTRACING_LIST);
|
||||
ERR_FAIL_COND(!raytracing_list.active);
|
||||
|
||||
ERR_FAIL_COND_MSG(p_data_size > MAX_PUSH_CONSTANT_SIZE, "Push constants can't be bigger than 128 bytes to maintain compatibility.");
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_MSG(p_data_size != raytracing_list.validation.pipeline_push_constant_size,
|
||||
"This raytracing pipeline requires (" + itos(raytracing_list.validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")");
|
||||
#endif
|
||||
|
||||
draw_graph.add_raytracing_list_set_push_constant(raytracing_list.state.pipeline_shader_driver_id, p_data, p_data_size);
|
||||
|
||||
// Store it in the state in case we need to restart the raytracing list.
|
||||
memcpy(raytracing_list.state.push_constant_data, p_data, p_data_size);
|
||||
raytracing_list.state.push_constant_size = p_data_size;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
raytracing_list.validation.pipeline_push_constant_supplied = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderingDevice::raytracing_list_trace_rays(RaytracingListID p_list, uint32_t p_width, uint32_t p_height) {
|
||||
ERR_RENDER_THREAD_GUARD();
|
||||
|
||||
ERR_FAIL_COND(p_list != ID_TYPE_RAYTRACING_LIST);
|
||||
ERR_FAIL_COND(!raytracing_list.active);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_NULL_MSG(shader_owner.get_or_null(raytracing_list.state.pipeline_shader), "No shader was set before attempting to trace rays.");
|
||||
ERR_FAIL_NULL_MSG(raytracing_pipeline_owner.get_or_null(raytracing_list.state.pipeline), "No raytracing pipeline was set before attempting to trace rays.");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
ERR_FAIL_COND_MSG(!raytracing_list.validation.pipeline_active, "No raytracing pipeline was set before attempting to draw.");
|
||||
|
||||
if (raytracing_list.validation.pipeline_push_constant_size > 0) {
|
||||
// Using push constants, check that they were supplied.
|
||||
ERR_FAIL_COND_MSG(!raytracing_list.validation.pipeline_push_constant_supplied,
|
||||
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
for (uint32_t i = 0; i < raytracing_list.state.set_count; i++) {
|
||||
if (raytracing_list.state.sets[i].pipeline_expected_format == 0) {
|
||||
// Nothing expected by this pipeline.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (raytracing_list.state.sets[i].pipeline_expected_format != raytracing_list.state.sets[i].uniform_set_format) {
|
||||
if (raytracing_list.state.sets[i].uniform_set_format == 0) {
|
||||
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
|
||||
} else if (uniform_set_owner.owns(raytracing_list.state.sets[i].uniform_set)) {
|
||||
UniformSet *us = uniform_set_owner.get_or_null(raytracing_list.state.sets[i].uniform_set);
|
||||
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(raytracing_list.state.pipeline_shader));
|
||||
} else {
|
||||
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(raytracing_list.state.pipeline_shader));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Prepare descriptor sets if the API doesn't use pipeline barriers.
|
||||
if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
|
||||
for (uint32_t i = 0; i < raytracing_list.state.set_count; i++) {
|
||||
if (raytracing_list.state.sets[i].pipeline_expected_format == 0) {
|
||||
// Nothing expected by this pipeline.
|
||||
continue;
|
||||
}
|
||||
|
||||
draw_graph.add_raytracing_list_uniform_set_prepare_for_use(raytracing_list.state.pipeline_shader_driver_id, raytracing_list.state.sets[i].uniform_set_driver_id, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind descriptor sets.
|
||||
for (uint32_t i = 0; i < raytracing_list.state.set_count; i++) {
|
||||
if (raytracing_list.state.sets[i].pipeline_expected_format == 0) {
|
||||
continue; // Nothing expected by this pipeline.
|
||||
}
|
||||
if (!raytracing_list.state.sets[i].bound) {
|
||||
// All good, see if this requires re-binding.
|
||||
draw_graph.add_raytracing_list_bind_uniform_set(raytracing_list.state.pipeline_shader_driver_id, raytracing_list.state.sets[i].uniform_set_driver_id, i);
|
||||
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(raytracing_list.state.sets[i].uniform_set);
|
||||
_uniform_set_update_shared(uniform_set);
|
||||
|
||||
draw_graph.add_raytracing_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
|
||||
|
||||
raytracing_list.state.sets[i].bound = true;
|
||||
}
|
||||
}
|
||||
|
||||
draw_graph.add_raytracing_list_trace_rays(p_width, p_height);
|
||||
raytracing_list.state.trace_count++;
|
||||
}
|
||||
|
||||
void RenderingDevice::raytracing_list_end() {
|
||||
ERR_RENDER_THREAD_GUARD();
|
||||
|
||||
ERR_FAIL_COND(!raytracing_list.active);
|
||||
|
||||
draw_graph.add_raytracing_list_end();
|
||||
|
||||
raytracing_list = RaytracingList();
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/**** COMPUTE LISTS ****/
|
||||
/***********************/
|
||||
|
|
@ -5373,7 +5940,8 @@ void RenderingDevice::draw_list_end() {
|
|||
RenderingDevice::ComputeListID RenderingDevice::compute_list_begin() {
|
||||
ERR_RENDER_THREAD_GUARD_V(INVALID_ID);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one draw/compute list can be active at the same time.");
|
||||
ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one compute list can be active at the same time.");
|
||||
ERR_FAIL_COND_V_MSG(raytracing_list.active, INVALID_ID, "Only one raytracing list can be active at the same time.");
|
||||
|
||||
compute_list.active = true;
|
||||
|
||||
|
|
@ -6101,7 +6669,7 @@ void RenderingDevice::_submit_transfer_workers(RDD::CommandBufferID p_draw_comma
|
|||
void RenderingDevice::_submit_transfer_barriers(RDD::CommandBufferID p_draw_command_buffer) {
|
||||
MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex);
|
||||
if (!transfer_worker_pool_texture_barriers.is_empty()) {
|
||||
driver->command_pipeline_barrier(p_draw_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, {}, {}, transfer_worker_pool_texture_barriers);
|
||||
driver->command_pipeline_barrier(p_draw_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, {}, {}, transfer_worker_pool_texture_barriers, {});
|
||||
transfer_worker_pool_texture_barriers.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -6400,6 +6968,13 @@ void RenderingDevice::_free_internal(RID p_id) {
|
|||
RDG::resource_tracker_free(storage_buffer->draw_tracker);
|
||||
frames[frame].buffers_to_dispose_of.push_back(*storage_buffer);
|
||||
storage_buffer_owner.free(p_id);
|
||||
} else if (instances_buffer_owner.owns(p_id)) {
|
||||
InstancesBuffer *instances_buffer = instances_buffer_owner.get_or_null(p_id);
|
||||
_check_transfer_worker_buffer(&instances_buffer->buffer);
|
||||
|
||||
RDG::resource_tracker_free(instances_buffer->buffer.draw_tracker);
|
||||
frames[frame].buffers_to_dispose_of.push_back(instances_buffer->buffer);
|
||||
instances_buffer_owner.free(p_id);
|
||||
} else if (uniform_set_owner.owns(p_id)) {
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id);
|
||||
frames[frame].uniform_sets_to_dispose_of.push_back(*uniform_set);
|
||||
|
|
@ -6416,6 +6991,14 @@ void RenderingDevice::_free_internal(RID p_id) {
|
|||
ComputePipeline *pipeline = compute_pipeline_owner.get_or_null(p_id);
|
||||
frames[frame].compute_pipelines_to_dispose_of.push_back(*pipeline);
|
||||
compute_pipeline_owner.free(p_id);
|
||||
} else if (acceleration_structure_owner.owns(p_id)) {
|
||||
AccelerationStructure *acceleration_structure = acceleration_structure_owner.get_or_null(p_id);
|
||||
frames[frame].acceleration_structures_to_dispose_of.push_back(*acceleration_structure);
|
||||
acceleration_structure_owner.free(p_id);
|
||||
} else if (raytracing_pipeline_owner.owns(p_id)) {
|
||||
RaytracingPipeline *pipeline = raytracing_pipeline_owner.get_or_null(p_id);
|
||||
frames[frame].raytracing_pipelines_to_dispose_of.push_back(*pipeline);
|
||||
raytracing_pipeline_owner.free(p_id);
|
||||
} else {
|
||||
#ifdef DEV_ENABLED
|
||||
ERR_PRINT("Attempted to free invalid ID: " + itos(p_id.get_id()) + " " + resource_name);
|
||||
|
|
@ -6459,6 +7042,9 @@ void RenderingDevice::set_resource_name(RID p_id, const String &p_name) {
|
|||
} else if (storage_buffer_owner.owns(p_id)) {
|
||||
Buffer *storage_buffer = storage_buffer_owner.get_or_null(p_id);
|
||||
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, storage_buffer->driver_id, p_name);
|
||||
} else if (instances_buffer_owner.owns(p_id)) {
|
||||
InstancesBuffer *instances_buffer = instances_buffer_owner.get_or_null(p_id);
|
||||
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, instances_buffer->buffer.driver_id, p_name);
|
||||
} else if (uniform_set_owner.owns(p_id)) {
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id);
|
||||
driver->set_object_name(RDD::OBJECT_TYPE_UNIFORM_SET, uniform_set->driver_id, p_name);
|
||||
|
|
@ -6468,6 +7054,12 @@ void RenderingDevice::set_resource_name(RID p_id, const String &p_name) {
|
|||
} else if (compute_pipeline_owner.owns(p_id)) {
|
||||
ComputePipeline *pipeline = compute_pipeline_owner.get_or_null(p_id);
|
||||
driver->set_object_name(RDD::OBJECT_TYPE_PIPELINE, pipeline->driver_id, p_name);
|
||||
} else if (acceleration_structure_owner.owns(p_id)) {
|
||||
AccelerationStructure *acceleration_structure = acceleration_structure_owner.get_or_null(p_id);
|
||||
driver->set_object_name(RDD::OBJECT_TYPE_ACCELERATION_STRUCTURE, acceleration_structure->driver_id, p_name);
|
||||
} else if (raytracing_pipeline_owner.owns(p_id)) {
|
||||
RaytracingPipeline *pipeline = raytracing_pipeline_owner.get_or_null(p_id);
|
||||
driver->set_object_name(RDD::OBJECT_TYPE_RAYTRACING_PIPELINE, pipeline->driver_id, p_name);
|
||||
} else {
|
||||
ERR_PRINT("Attempted to name invalid ID: " + itos(p_id.get_id()));
|
||||
return;
|
||||
|
|
@ -6585,6 +7177,26 @@ void RenderingDevice::_free_pending_resources(int p_frame) {
|
|||
frames[p_frame].compute_pipelines_to_dispose_of.pop_front();
|
||||
}
|
||||
|
||||
while (frames[p_frame].raytracing_pipelines_to_dispose_of.front()) {
|
||||
RaytracingPipeline *pipeline = &frames[p_frame].raytracing_pipelines_to_dispose_of.front()->get();
|
||||
|
||||
driver->raytracing_pipeline_free(pipeline->driver_id);
|
||||
|
||||
frames[p_frame].raytracing_pipelines_to_dispose_of.pop_front();
|
||||
}
|
||||
|
||||
// Acceleration structures.
|
||||
while (frames[p_frame].acceleration_structures_to_dispose_of.front()) {
|
||||
AccelerationStructure &acceleration_structure = frames[p_frame].acceleration_structures_to_dispose_of.front()->get();
|
||||
|
||||
if (acceleration_structure.scratch_buffer != RID()) {
|
||||
free_rid(acceleration_structure.scratch_buffer);
|
||||
}
|
||||
driver->acceleration_structure_free(acceleration_structure.driver_id);
|
||||
|
||||
frames[p_frame].acceleration_structures_to_dispose_of.pop_front();
|
||||
}
|
||||
|
||||
// Uniform sets.
|
||||
while (frames[p_frame].uniform_sets_to_dispose_of.front()) {
|
||||
UniformSet *uniform_set = &frames[p_frame].uniform_sets_to_dispose_of.front()->get();
|
||||
|
|
@ -6733,6 +7345,10 @@ void RenderingDevice::_end_frame() {
|
|||
ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work).");
|
||||
}
|
||||
|
||||
if (raytracing_list.active) {
|
||||
ERR_PRINT("Found open raytracing list at the end of the frame, this should never happen (further raytracing will likely not work).");
|
||||
}
|
||||
|
||||
// The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use.
|
||||
RDD::CommandBufferID command_buffer = frames[frame].command_buffer;
|
||||
GodotProfileZoneGroupedFirst(_profile_zone, "_submit_transfer_workers");
|
||||
|
|
@ -7187,6 +7803,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
|
|||
|
||||
draw_list = DrawList();
|
||||
compute_list = ComputeList();
|
||||
raytracing_list = RaytracingList();
|
||||
|
||||
bool project_pipeline_cache_enable = GLOBAL_GET("rendering/rendering_device/pipeline_cache/enable");
|
||||
if (is_main_instance && project_pipeline_cache_enable) {
|
||||
|
|
@ -7312,6 +7929,7 @@ void RenderingDevice::capture_timestamp(const String &p_name) {
|
|||
|
||||
ERR_FAIL_COND_MSG(draw_list.active && draw_list.state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
|
||||
ERR_FAIL_COND_MSG(compute_list.active && compute_list.state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name);
|
||||
ERR_FAIL_COND_MSG(raytracing_list.active && raytracing_list.state.trace_count > 0, "Capturing timestamps during raytracing list creation is not allowed. Offending timestamp was: " + p_name);
|
||||
ERR_FAIL_COND_MSG(frames[frame].timestamp_count >= max_timestamp_query_elements, vformat("Tried capturing more timestamps than the configured maximum (%d). You can increase this limit in the project settings under 'Debug/Settings' called 'Max Timestamp Query Elements'.", max_timestamp_query_elements));
|
||||
|
||||
draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count);
|
||||
|
|
@ -7368,6 +7986,8 @@ uint64_t RenderingDevice::get_driver_resource(DriverResource p_resource, RID p_r
|
|||
buffer = texture_buffer_owner.get_or_null(p_rid);
|
||||
} else if (storage_buffer_owner.owns(p_rid)) {
|
||||
buffer = storage_buffer_owner.get_or_null(p_rid);
|
||||
} else if (instances_buffer_owner.owns(p_rid)) {
|
||||
buffer = &instances_buffer_owner.get_or_null(p_rid)->buffer;
|
||||
}
|
||||
ERR_FAIL_NULL_V(buffer, 0);
|
||||
|
||||
|
|
@ -7489,6 +8109,7 @@ void RenderingDevice::finalize() {
|
|||
_free_rids(uniform_set_owner, "UniformSet");
|
||||
_free_rids(texture_buffer_owner, "TextureBuffer");
|
||||
_free_rids(storage_buffer_owner, "StorageBuffer");
|
||||
_free_rids(instances_buffer_owner, "InstancesBuffer");
|
||||
_free_rids(uniform_buffer_owner, "UniformBuffer");
|
||||
_free_rids(shader_owner, "Shader");
|
||||
_free_rids(index_array_owner, "IndexArray");
|
||||
|
|
@ -7731,6 +8352,15 @@ void RenderingDevice::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader", "specialization_constants"), &RenderingDevice::_compute_pipeline_create, DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
|
||||
ClassDB::bind_method(D_METHOD("compute_pipeline_is_valid", "compute_pipeline"), &RenderingDevice::compute_pipeline_is_valid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("raytracing_pipeline_create", "shader", "specialization_constants"), &RenderingDevice::_raytracing_pipeline_create, DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
|
||||
ClassDB::bind_method(D_METHOD("raytracing_pipeline_is_valid", "raytracing_pipeline"), &RenderingDevice::raytracing_pipeline_is_valid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("blas_create", "vertex_array", "index_array", "geometry_bits", "position_attribute_location"), &RenderingDevice::blas_create, DEFVAL(0), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("tlas_instances_buffer_create", "instance_count", "creation_bits"), &RenderingDevice::tlas_instances_buffer_create, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("tlas_instances_buffer_fill", "instances_buffer", "blases", "transforms"), &RenderingDevice::_tlas_instances_buffer_fill);
|
||||
ClassDB::bind_method(D_METHOD("tlas_create", "instances_buffer"), &RenderingDevice::tlas_create);
|
||||
ClassDB::bind_method(D_METHOD("acceleration_structure_build", "acceleration_structure"), &RenderingDevice::acceleration_structure_build);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_height", "screen"), &RenderingDevice::screen_get_height, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_framebuffer_format", "screen"), &RenderingDevice::screen_get_framebuffer_format, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
|
|
@ -7772,6 +8402,13 @@ void RenderingDevice::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier);
|
||||
ClassDB::bind_method(D_METHOD("compute_list_end"), &RenderingDevice::compute_list_end);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("raytracing_list_begin"), &RenderingDevice::raytracing_list_begin);
|
||||
ClassDB::bind_method(D_METHOD("raytracing_list_bind_raytracing_pipeline", "raytracing_list", "raytracing_pipeline"), &RenderingDevice::raytracing_list_bind_raytracing_pipeline);
|
||||
ClassDB::bind_method(D_METHOD("raytracing_list_set_push_constant", "raytracing_list", "buffer", "size_bytes"), &RenderingDevice::_raytracing_list_set_push_constant);
|
||||
ClassDB::bind_method(D_METHOD("raytracing_list_bind_uniform_set", "raytracing_list", "uniform_set", "set_index"), &RenderingDevice::raytracing_list_bind_uniform_set);
|
||||
ClassDB::bind_method(D_METHOD("raytracing_list_trace_rays", "raytracing_list", "width", "height"), &RenderingDevice::raytracing_list_trace_rays);
|
||||
ClassDB::bind_method(D_METHOD("raytracing_list_end"), &RenderingDevice::raytracing_list_end);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingDevice::free_rid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("capture_timestamp", "name"), &RenderingDevice::capture_timestamp);
|
||||
|
|
@ -8176,6 +8813,10 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_BITFIELD_FLAG(BUFFER_CREATION_AS_STORAGE_BIT);
|
||||
// Not exposed on purpose. This flag is too dangerous to be exposed to regular GD users.
|
||||
//BIND_BITFIELD_FLAG(BUFFER_CREATION_DYNAMIC_PERSISTENT_BIT);
|
||||
BIND_BITFIELD_FLAG(BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT);
|
||||
|
||||
BIND_BITFIELD_FLAG(ACCELERATION_STRUCTURE_GEOMETRY_OPAQUE);
|
||||
BIND_BITFIELD_FLAG(ACCELERATION_STRUCTURE_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION);
|
||||
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type)
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture
|
||||
|
|
@ -8189,6 +8830,7 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_INPUT_ATTACHMENT); //used for sub-pass read/write); for mobile mostly
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC); // Exposed in case a BUFFER_CREATION_DYNAMIC_PERSISTENT_BIT buffer created by C++ makes it into GD users.
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC); // Exposed in case a BUFFER_CREATION_DYNAMIC_PERSISTENT_BIT buffer created by C++ makes it into GD users.
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_ACCELERATION_STRUCTURE); //acceleration structure (TLAS)); for raytracing
|
||||
BIND_ENUM_CONSTANT(UNIFORM_TYPE_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_POINTS);
|
||||
|
|
@ -8308,12 +8950,22 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_CONTROL);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_EVALUATION);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_COMPUTE);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_RAYGEN);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_ANY_HIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_CLOSEST_HIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_MISS);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_INTERSECTION);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_MAX);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_VERTEX_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_FRAGMENT_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_CONTROL_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_EVALUATION_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_COMPUTE_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_RAYGEN_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_ANY_HIT_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_CLOSEST_HIT_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_MISS_BIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_STAGE_INTERSECTION_BIT);
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_GLSL);
|
||||
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_HLSL);
|
||||
|
|
@ -8326,6 +8978,8 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(SUPPORTS_METALFX_TEMPORAL);
|
||||
BIND_ENUM_CONSTANT(SUPPORTS_BUFFER_DEVICE_ADDRESS);
|
||||
BIND_ENUM_CONSTANT(SUPPORTS_IMAGE_ATOMIC_32_BIT);
|
||||
BIND_ENUM_CONSTANT(SUPPORTS_RAY_QUERY);
|
||||
BIND_ENUM_CONSTANT(SUPPORTS_RAYTRACING_PIPELINE);
|
||||
|
||||
BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
|
||||
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
|
||||
|
|
@ -8637,6 +9291,16 @@ Error RenderingDevice::_buffer_update_bind(RID p_buffer, uint32_t p_offset, uint
|
|||
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr());
|
||||
}
|
||||
|
||||
void RenderingDevice::_tlas_instances_buffer_fill(RID p_instances_buffer, const TypedArray<RID> &p_blases, const TypedArray<Transform3D> &p_transforms) {
|
||||
Vector<RID> blases = Variant(p_blases);
|
||||
Vector<Transform3D> transforms;
|
||||
transforms.resize(p_transforms.size());
|
||||
for (int i = 0; i < p_transforms.size(); i++) {
|
||||
transforms.write[i] = p_transforms[i];
|
||||
}
|
||||
tlas_instances_buffer_fill(p_instances_buffer, blases, transforms);
|
||||
}
|
||||
|
||||
static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constants(const TypedArray<RDPipelineSpecializationConstant> &p_constants) {
|
||||
Vector<RenderingDevice::PipelineSpecializationConstant> ret;
|
||||
ret.resize(p_constants.size());
|
||||
|
|
@ -8705,6 +9369,10 @@ RID RenderingDevice::_compute_pipeline_create(RID p_shader, const TypedArray<RDP
|
|||
return compute_pipeline_create(p_shader, _get_spec_constants(p_specialization_constants));
|
||||
}
|
||||
|
||||
RID RenderingDevice::_raytracing_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants = TypedArray<RDPipelineSpecializationConstant>()) {
|
||||
return raytracing_pipeline_create(p_shader, _get_spec_constants(p_specialization_constants));
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
|
||||
ERR_FAIL_V_MSG(Vector<int64_t>(), "Deprecated. Split draw lists are used automatically by RenderingDevice.");
|
||||
|
|
@ -8725,6 +9393,11 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons
|
|||
compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
|
||||
}
|
||||
|
||||
void RenderingDevice::_raytracing_list_set_push_constant(RaytracingListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
|
||||
ERR_FAIL_COND(p_data_size > (uint32_t)p_data.size());
|
||||
raytracing_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
|
||||
}
|
||||
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_NONE, RDG::RESOURCE_USAGE_NONE));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_COPY_FROM, RDG::RESOURCE_USAGE_COPY_FROM));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_COPY_TO, RDG::RESOURCE_USAGE_COPY_TO));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue