Fix #137909: Vulkan: Recover from allocation errors
When buffers/images are allocated that use larger limits than supported by the GPU blender would crash. This PR adds some safety mechanism to allow Blender to recover from allocation errors. This has been tested on NVIDIA drivers. Pull Request: https://projects.blender.org/blender/blender/pulls/139876
This commit is contained in:
@@ -63,7 +63,11 @@ class VKDrawIndexedIndirectNode
|
||||
const CreateInfo &create_info) override
|
||||
{
|
||||
create_info.resources.build_links(resources, node_links);
|
||||
vk_index_buffer_binding_build_links(resources, node_links, create_info.node_data.index_buffer);
|
||||
if (create_info.node_data.index_buffer.buffer != VK_NULL_HANDLE) {
|
||||
vk_index_buffer_binding_build_links(
|
||||
resources, node_links, create_info.node_data.index_buffer);
|
||||
}
|
||||
|
||||
vk_vertex_buffer_bindings_build_links(
|
||||
resources, node_links, create_info.node_data.vertex_buffers);
|
||||
ResourceWithStamp buffer_resource = resources.get_buffer(
|
||||
|
||||
@@ -30,6 +30,9 @@ bool VKBuffer::create(size_t size_in_bytes,
|
||||
BLI_assert(!is_allocated());
|
||||
BLI_assert(vk_buffer_ == VK_NULL_HANDLE);
|
||||
BLI_assert(mapped_memory_ == nullptr);
|
||||
if (allocation_failed_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_in_bytes_ = size_in_bytes;
|
||||
/*
|
||||
@@ -77,6 +80,9 @@ bool VKBuffer::create(size_t size_in_bytes,
|
||||
VkResult result = vmaCreateBuffer(
|
||||
allocator, &create_info, &vma_create_info, &vk_buffer_, &allocation_, nullptr);
|
||||
if (result != VK_SUCCESS) {
|
||||
allocation_failed_ = true;
|
||||
size_in_bytes_ = 0;
|
||||
alloc_size_in_bytes_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ class VKBuffer : public NonCopyable {
|
||||
VmaAllocation allocation_ = VK_NULL_HANDLE;
|
||||
VkMemoryPropertyFlags vk_memory_property_flags_;
|
||||
TimelineValue async_timeline_ = 0;
|
||||
/** Has a previous allocation failed. Will skip reallocations. */
|
||||
bool allocation_failed_ = false;
|
||||
|
||||
/* Pointer to the virtually mapped memory. */
|
||||
void *mapped_memory_ = nullptr;
|
||||
|
||||
@@ -113,7 +113,7 @@ void VKDebuggingTools::deinit(VkInstance vk_instance)
|
||||
void object_label(VkObjectType vk_object_type, uint64_t object_handle, const char *name)
|
||||
{
|
||||
const VKDevice &device = VKBackend::get().device;
|
||||
if (G.debug & G_DEBUG_GPU && device.functions.vkSetDebugUtilsObjectName) {
|
||||
if (G.debug & G_DEBUG_GPU && device.functions.vkSetDebugUtilsObjectName && object_handle != 0) {
|
||||
VkDebugUtilsObjectNameInfoEXT info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||
info.objectType = vk_object_type;
|
||||
|
||||
@@ -163,11 +163,14 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
|
||||
.vk_handle(),
|
||||
VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR,
|
||||
resource_binding.location);
|
||||
access_info.images.append({texture->vk_image_handle(),
|
||||
resource_binding.access_mask,
|
||||
to_vk_image_aspect_flag_bits(texture->device_format_get()),
|
||||
0,
|
||||
VK_REMAINING_ARRAY_LAYERS});
|
||||
VkImage vk_image = texture->vk_image_handle();
|
||||
if (vk_image != VK_NULL_HANDLE) {
|
||||
access_info.images.append({texture->vk_image_handle(),
|
||||
resource_binding.access_mask,
|
||||
to_vk_image_aspect_flag_bits(texture->device_format_get()),
|
||||
0,
|
||||
VK_REMAINING_ARRAY_LAYERS});
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool supports_dynamic_rendering = device.extensions_get().dynamic_rendering;
|
||||
@@ -183,11 +186,14 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
|
||||
texture->image_view_get(resource_binding.arrayed, VKImageViewFlags::DEFAULT).vk_handle(),
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
resource_binding.location);
|
||||
access_info.images.append({texture->vk_image_handle(),
|
||||
resource_binding.access_mask,
|
||||
to_vk_image_aspect_flag_bits(texture->device_format_get()),
|
||||
0,
|
||||
VK_REMAINING_ARRAY_LAYERS});
|
||||
VkImage vk_image = texture->vk_image_handle();
|
||||
if (vk_image != VK_NULL_HANDLE) {
|
||||
access_info.images.append({vk_image,
|
||||
resource_binding.access_mask,
|
||||
to_vk_image_aspect_flag_bits(texture->device_format_get()),
|
||||
0,
|
||||
VK_REMAINING_ARRAY_LAYERS});
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Fall back to render-passes / sub-passes. */
|
||||
@@ -197,11 +203,14 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
|
||||
.vk_handle(),
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
resource_binding.location);
|
||||
access_info.images.append({texture->vk_image_handle(),
|
||||
resource_binding.access_mask,
|
||||
to_vk_image_aspect_flag_bits(texture->device_format_get()),
|
||||
0,
|
||||
VK_REMAINING_ARRAY_LAYERS});
|
||||
VkImage vk_image = texture->vk_image_handle();
|
||||
if (vk_image != VK_NULL_HANDLE) {
|
||||
access_info.images.append({vk_image,
|
||||
resource_binding.access_mask,
|
||||
to_vk_image_aspect_flag_bits(texture->device_format_get()),
|
||||
0,
|
||||
VK_REMAINING_ARRAY_LAYERS});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -260,7 +269,9 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
|
||||
elem.offset,
|
||||
vk_device_size - elem.offset,
|
||||
resource_binding.location);
|
||||
access_info.buffers.append({vk_buffer, resource_binding.access_mask});
|
||||
if (vk_buffer != VK_NULL_HANDLE) {
|
||||
access_info.buffers.append({vk_buffer, resource_binding.access_mask});
|
||||
}
|
||||
}
|
||||
|
||||
void VKDescriptorSetTracker::bind_uniform_buffer_resource(
|
||||
|
||||
Reference in New Issue
Block a user