Fix #135644: HIP-RT crash with host memory fallback

Avoid manipulating the host pointer in device memory, this fails when host
mapped memory gets used and the pointers gets re-allocated.

Pull Request: https://projects.blender.org/blender/blender/pulls/135724
This commit is contained in:
Brecht Van Lommel 2025-03-11 08:57:32 +01:00
parent 0ff2635131
commit 73ea95a56a

View File

@ -448,31 +448,31 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_triangle_blas(BVHHIPRT *bvh, Mesh *
} }
else { else {
size_t triangle_size = mesh->get_triangles().size(); size_t triangle_size = mesh->get_triangles().size();
void *triangle_data = mesh->get_triangles().data(); int *triangle_data = mesh->get_triangles().data();
size_t vertex_size = mesh->get_verts().size(); size_t vertex_size = mesh->get_verts().size();
void *vertex_data = mesh->get_verts().data(); float *vertex_data = reinterpret_cast<float *>(mesh->get_verts().data());
bvh->triangle_mesh.triangleCount = mesh->num_triangles(); bvh->triangle_mesh.triangleCount = mesh->num_triangles();
bvh->triangle_mesh.triangleStride = 3 * sizeof(int); bvh->triangle_mesh.triangleStride = 3 * sizeof(int);
bvh->triangle_mesh.vertexCount = vertex_size; bvh->triangle_mesh.vertexCount = vertex_size;
bvh->triangle_mesh.vertexStride = sizeof(float3); bvh->triangle_mesh.vertexStride = sizeof(float3);
bvh->triangle_index.host_pointer = triangle_data; /* TODO: reduce memory usage by avoiding copy. */
bvh->triangle_index.data_elements = 1; int *triangle_index_data = bvh->triangle_index.resize(triangle_size);
bvh->triangle_index.data_type = TYPE_INT; float *vertex_data_data = bvh->vertex_data.resize(vertex_size * 4);
bvh->triangle_index.data_size = triangle_size;
bvh->triangle_index.copy_to_device(); if (triangle_index_data && vertex_data_data) {
std::copy_n(triangle_data, triangle_size, triangle_index_data);
std::copy_n(vertex_data, vertex_size * 4, vertex_data_data);
static_assert(sizeof(float3) == sizeof(float) * 4);
bvh->triangle_index.copy_to_device();
bvh->vertex_data.copy_to_device();
}
bvh->triangle_mesh.triangleIndices = (void *)(bvh->triangle_index.device_pointer); bvh->triangle_mesh.triangleIndices = (void *)(bvh->triangle_index.device_pointer);
// either has to set the host pointer to zero, or increment the refcount on triangle_data
bvh->triangle_index.host_pointer = nullptr;
bvh->vertex_data.host_pointer = vertex_data;
bvh->vertex_data.data_elements = 4;
bvh->vertex_data.data_type = TYPE_FLOAT;
bvh->vertex_data.data_size = vertex_size;
bvh->vertex_data.copy_to_device();
bvh->triangle_mesh.vertices = (void *)(bvh->vertex_data.device_pointer); bvh->triangle_mesh.vertices = (void *)(bvh->vertex_data.device_pointer);
bvh->vertex_data.host_pointer = nullptr;
geom_input.type = hiprtPrimitiveTypeTriangleMesh; geom_input.type = hiprtPrimitiveTypeTriangleMesh;
geom_input.primitive.triangleMesh = bvh->triangle_mesh; geom_input.primitive.triangleMesh = bvh->triangle_mesh;
@ -1027,19 +1027,16 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
} }
{ {
if (instance_transform_matrix.data_size != frame_count) { /* TODO: reduce memory usage by avoiding copy. */
assert(!instance_transform_matrix.host_pointer); hiprtFrameMatrix *instance_transform_matrix_data = instance_transform_matrix.resize(
instance_transform_matrix.host_and_device_free(); frame_count);
if (instance_transform_matrix_data == nullptr) {
set_error("Failed to allocate host instance_transform_matrix for TLAS");
return nullptr;
} }
instance_transform_matrix.host_pointer = transform_matrix.data();
instance_transform_matrix.data_elements = sizeof(hiprtFrameMatrix); std::copy_n(transform_matrix.data(), frame_count, instance_transform_matrix_data);
instance_transform_matrix.data_type = TYPE_UCHAR;
instance_transform_matrix.data_size = frame_count;
instance_transform_matrix.data_width = frame_count;
instance_transform_matrix.data_height = 0;
instance_transform_matrix.data_depth = 0;
instance_transform_matrix.copy_to_device(); instance_transform_matrix.copy_to_device();
instance_transform_matrix.host_pointer = nullptr;
if (instance_transform_matrix.device_pointer == 0) { if (instance_transform_matrix.device_pointer == 0) {
set_error("Failed to allocate instance_transform_matrix for TLAS"); set_error("Failed to allocate instance_transform_matrix for TLAS");
@ -1099,23 +1096,20 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
} }
if (bvh->custom_prim_info.size()) { if (bvh->custom_prim_info.size()) {
size_t data_size = bvh->custom_prim_info.size(); /* TODO: reduce memory usage by avoiding copy. */
if (custom_prim_info.data_size != data_size) { const size_t data_size = bvh->custom_prim_info.size();
assert(!custom_prim_info.host_pointer); int2 *custom_prim_info_data = custom_prim_info.resize(data_size);
custom_prim_info.host_and_device_free(); if (custom_prim_info_data == nullptr) {
set_error("Failed to allocate host custom_prim_info_data for TLAS");
hiprtDestroyScene(hiprt_context, scene);
return nullptr;
} }
custom_prim_info.host_pointer = bvh->custom_prim_info.data();
custom_prim_info.data_elements = 2;
custom_prim_info.data_type = TYPE_INT;
custom_prim_info.data_size = data_size;
custom_prim_info.data_width = data_size;
custom_prim_info.data_height = 0;
custom_prim_info.data_depth = 0;
custom_prim_info.copy_to_device();
custom_prim_info.host_pointer = nullptr;
std::copy_n(bvh->custom_prim_info.data(), data_size, custom_prim_info_data);
custom_prim_info.copy_to_device();
custom_prim_info_offset.copy_to_device(); custom_prim_info_offset.copy_to_device();
if (!custom_prim_info.device_pointer) { if (custom_prim_info.device_pointer == 0 || custom_prim_info.device_pointer == 0) {
set_error("Failed to allocate custom_prim_info_offset for TLAS"); set_error("Failed to allocate custom_prim_info_offset for TLAS");
hiprtDestroyScene(hiprt_context, scene); hiprtDestroyScene(hiprt_context, scene);
return nullptr; return nullptr;
@ -1123,24 +1117,22 @@ hiprtScene HIPRTDevice::build_tlas(BVHHIPRT *bvh,
} }
if (bvh->prims_time.size()) { if (bvh->prims_time.size()) {
size_t data_size = bvh->prims_time.size(); /* TODO: reduce memory usage by avoiding copy. */
if (prims_time.data_size != data_size) { const size_t data_size = bvh->prims_time.size();
assert(!prims_time.host_pointer); float2 *prims_time_data = prims_time.resize(data_size);
prims_time.host_and_device_free(); if (prims_time_data == nullptr) {
set_error("Failed to allocate host prims_time for TLAS");
hiprtDestroyScene(hiprt_context, scene);
return nullptr;
} }
prims_time.host_pointer = bvh->prims_time.data();
prims_time.data_elements = 2;
prims_time.data_type = TYPE_FLOAT;
prims_time.data_size = data_size;
prims_time.data_width = data_size;
prims_time.data_height = 0;
prims_time.data_depth = 0;
prims_time.copy_to_device();
prims_time.host_pointer = nullptr;
std::copy_n(bvh->prims_time.data(), data_size, prims_time_data);
prims_time.copy_to_device();
prim_time_offset.copy_to_device(); prim_time_offset.copy_to_device();
if (!prim_time_offset.device_pointer) {
set_error("Failed to allocate prim_time_offset_offset for TLAS"); if (prim_time_offset.device_pointer == 0 || prims_time.device_pointer == 0) {
set_error("Failed to allocate prims_time for TLAS");
hiprtDestroyScene(hiprt_context, scene); hiprtDestroyScene(hiprt_context, scene);
return nullptr; return nullptr;
} }