From f2fc4473f0053cc69dca4754e0f5cca0335f1ccc Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 5 May 2026 00:14:38 +0200 Subject: [PATCH] Improve Vulkan error messages to be more user-friendly - Mention that error codes are VkResult error codes (as opposed to Godot error codes). - Mention passed values in more cases to help troubleshooting. - Mention common causes of "Vulkan device lost" in crash message. - Use consistent style across all errors. --- .../rendering_context_driver_vulkan.cpp | 6 +- .../vulkan/rendering_device_driver_vulkan.cpp | 182 +++++++++--------- 2 files changed, 99 insertions(+), 89 deletions(-) diff --git a/drivers/vulkan/rendering_context_driver_vulkan.cpp b/drivers/vulkan/rendering_context_driver_vulkan.cpp index 28b45ee0d7..01510a55ea 100644 --- a/drivers/vulkan/rendering_context_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_context_driver_vulkan.cpp @@ -475,7 +475,7 @@ Error RenderingContextDriverVulkan::_initialize_instance_extensions() { #ifdef DEV_ENABLED for (uint32_t i = 0; i < instance_extension_count; i++) { - print_verbose(String("VULKAN: Found instance extension ") + String::utf8(instance_extensions[i].extensionName) + String(".")); + print_verbose(String("Vulkan: Found instance extension ") + String::utf8(instance_extensions[i].extensionName) + String(".")); } #endif @@ -491,9 +491,9 @@ Error RenderingContextDriverVulkan::_initialize_instance_extensions() { for (KeyValue &requested_extension : requested_instance_extensions) { if (!enabled_instance_extension_names.has(requested_extension.key)) { if (requested_extension.value) { - ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String::utf8(requested_extension.key) + String(" not found.")); + ERR_FAIL_V_MSG(ERR_BUG, String("Required Vulkan instance extension ") + String::utf8(requested_extension.key) + String(" not found.")); } else { - print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found.")); + print_verbose(String("Optional Vulkan instance extension ") + String::utf8(requested_extension.key) + String(" not found.")); } } } diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index 2dbc50b74f..b46a67ec99 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -617,13 +617,13 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() { uint32_t device_extension_count = 0; VkResult err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, nullptr); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); - ERR_FAIL_COND_V_MSG(device_extension_count == 0, ERR_CANT_CREATE, "vkEnumerateDeviceExtensionProperties failed to find any extensions\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?"); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan device extension count (VkResult error %d).", err)); + ERR_FAIL_COND_V_MSG(device_extension_count == 0, ERR_CANT_CREATE, "Couldn't find any Vulkan device extensions. Do you have a compatible Vulkan installable client driver (ICD) installed?"); TightLocalVector device_extensions; device_extensions.resize(device_extension_count); err = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_count, device_extensions.ptr()); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan device extension properties (VkResult error %d).", err)); #if defined(SWAPPY_FRAME_PACING_ENABLED) if (swappy_frame_pacer_enable) { @@ -658,7 +658,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() { #ifdef DEV_ENABLED for (uint32_t i = 0; i < device_extension_count; i++) { - print_verbose(String("VULKAN: Found device extension ") + String::utf8(device_extensions[i].extensionName)); + print_verbose(String("Vulkan: Found device extension ") + String::utf8(device_extensions[i].extensionName)); } #endif @@ -674,9 +674,9 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() { for (KeyValue &requested_extension : requested_device_extensions) { if (!enabled_device_extension_names.has(requested_extension.key)) { if (requested_extension.value) { - ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String::utf8(requested_extension.key) + String(" not found.")); + ERR_FAIL_V_MSG(ERR_BUG, String("Required Vulkan device extension ") + String::utf8(requested_extension.key) + String(" not found.")); } else { - print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found")); + print_verbose(String("Optional Vulkan device extension ") + String::utf8(requested_extension.key) + String(" not found")); } } } @@ -1410,10 +1410,10 @@ Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVectorcreate_vulkan_device(&create_info, &vk_device); - ERR_FAIL_COND_V(!device_created, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(!device_created, ERR_CANT_CREATE, "Couldn't create a Vulkan device through the VulkanHooks singleton."); } else { VkResult err = vkCreateDevice(physical_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DEVICE), &vk_device); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't create Vulkan device (VkResult error %d).", err)); } for (uint32_t i = 0; i < queue_families.size(); i++) { @@ -1474,7 +1474,7 @@ Error RenderingDeviceDriverVulkan::_initialize_allocator() { allocator_info.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; } VkResult err = vmaCreateAllocator(&allocator_info, &allocator); - ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "vmaCreateAllocator failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, vformat("Couldn't create Vulkan memory allocator (VkResult error %d).", err)); return OK; } @@ -1619,7 +1619,7 @@ bool RenderingDeviceDriverVulkan::_recreate_image_semaphore(CommandQueue *p_comm VkSemaphoreCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; VkResult err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore); - ERR_FAIL_COND_V(err != VK_SUCCESS, false); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, false, vformat("Couldn't create Vulkan semaphore (VkResult error %d).", err)); // Indicate the semaphore is free again and destroy the previous one before storing the new one. vkDestroySemaphore(vk_device, p_command_queue->image_semaphores[p_semaphore_index], VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE)); @@ -1771,26 +1771,26 @@ Error RenderingDeviceDriverVulkan::initialize(uint32_t p_device_index, uint32_t } Error err = _initialize_device_extensions(); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan device extensions. This may be caused by an incompatible or outdated graphics driver."); err = _check_device_features(); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan device features. This may be caused by an incompatible or outdated graphics driver."); err = _check_device_capabilities(); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan device capabilities. This may be caused by an incompatible or outdated graphics driver."); LocalVector queue_create_info; err = _add_queue_create_info(queue_create_info); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan device queue. This may be caused by an incompatible or outdated graphics driver."); err = _initialize_device(queue_create_info); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan device. This may be caused by an incompatible or outdated graphics driver."); err = _initialize_allocator(); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan memory allocator. This may be caused by an incompatible or outdated graphics driver."); err = _initialize_pipeline_cache(); - ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't initialize Vulkan pipeline cache. This may be caused by an incompatible or outdated graphics driver."); max_descriptor_sets_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool"); @@ -1814,7 +1814,7 @@ Error RenderingDeviceDriverVulkan::initialize(uint32_t p_device_index, uint32_t #if RECORD_PIPELINE_STATISTICS pipeline_statistics.file_access = FileAccess::open(RECORD_PIPELINE_STATISTICS_PATH, FileAccess::WRITE); - ERR_FAIL_NULL_V_MSG(pipeline_statistics.file_access, ERR_CANT_CREATE, "Unable to write pipeline statistics file."); + ERR_FAIL_NULL_V_MSG(pipeline_statistics.file_access, ERR_CANT_CREATE, "Couldn't write Vulkan pipeline statistics file."); pipeline_statistics.file_access->store_csv_line({ "name", "hash", "stage", "spec", "glslang", "re-spirv", "time" }); pipeline_statistics.file_access->flush(); @@ -1848,7 +1848,7 @@ VmaPool RenderingDeviceDriverVulkan::_find_or_create_small_allocs_pool(uint32_t VmaPool pool = VK_NULL_HANDLE; VkResult res = vmaCreatePool(allocator, &pci, &pool); small_allocs_pools[p_mem_type_index] = pool; // Don't try to create it again if failed the first time. - ERR_FAIL_COND_V_MSG(res, pool, "vmaCreatePool failed with error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, pool, vformat("Couldn't create Vulkan memory allocator pool (VkResult error %d)", res)); return pool; } @@ -1944,14 +1944,14 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie alloc_create_info.preferredFlags &= ~vma_flags_to_remove; alloc_create_info.usage = vma_usage; VkResult err = vmaCreateBuffer(allocator, &create_info, &alloc_create_info, &vk_buffer, &allocation, &alloc_info); - ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, BufferID(), vformat("Can't create buffer of size: %d (VkResult error %d).", p_size, err)); } else { VkResult err = vkCreateBuffer(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER), &vk_buffer); - ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, BufferID(), vformat("Can't create buffer of size: %d (VkResult error %d).", p_size, err)); err = vmaAllocateMemoryForBuffer(allocator, vk_buffer, &alloc_create_info, &allocation, &alloc_info); - ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't allocate memory for buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, BufferID(), vformat("Can't allocate memory for buffer of size: %d (VkResult error %d).", p_size, err)); err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, nullptr); - ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't bind memory to buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, BufferID(), vformat("Can't bind memory to buffer of size: %d (VkResult error %d).", p_size, err)); } // Bookkeep. @@ -1959,7 +1959,7 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie if (p_usage.has_flag(BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT)) { void *persistent_ptr = nullptr; VkResult err = vmaMapMemory(allocator, allocation, &persistent_ptr); - ERR_FAIL_COND_V_MSG(err, BufferID(), "vmaMapMemory failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, BufferID(), vformat("Couldn't map Vulkan buffer memory (VkResult error %d).", err)); BufferDynamicInfo *dyn_buffer = VersatileResource::allocate(resources_allocator); buf_info = dyn_buffer; @@ -1991,7 +1991,7 @@ bool RenderingDeviceDriverVulkan::buffer_set_texel_format(BufferID p_buffer, Dat view_create_info.range = buf_info->allocation.size; VkResult res = vkCreateBufferView(vk_device, &view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW), &buf_info->vk_view); - ERR_FAIL_COND_V_MSG(res, false, "Unable to create buffer view, error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, false, vformat("Couldn't create Vulkan buffer view (VkResult error %d).", res)); return true; } @@ -2030,7 +2030,7 @@ uint8_t *RenderingDeviceDriverVulkan::buffer_map(BufferID p_buffer) { ERR_FAIL_COND_V_MSG(buf_info->is_dynamic(), nullptr, "Buffer must NOT have BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT. Use buffer_persistent_map_advance() instead."); void *data_ptr = nullptr; VkResult err = vmaMapMemory(allocator, buf_info->allocation.handle, &data_ptr); - ERR_FAIL_COND_V_MSG(err, nullptr, "vmaMapMemory failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, nullptr, vformat("Couldn't map buffer memory (VkResult error %d).", err)); return (uint8_t *)data_ptr; } @@ -2043,7 +2043,7 @@ uint8_t *RenderingDeviceDriverVulkan::buffer_persistent_map_advance(BufferID p_b BufferDynamicInfo *buf_info = (BufferDynamicInfo *)p_buffer.id; ERR_FAIL_COND_V_MSG(!buf_info->is_dynamic(), nullptr, "Buffer must have BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT. Use buffer_map() instead."); #ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(buf_info->last_frame_mapped == p_frames_drawn, nullptr, "Buffers with BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT must only be mapped once per frame. Otherwise there could be race conditions with the GPU. Amalgamate all data uploading into one map(), use an extra buffer or remove the bit."); + ERR_FAIL_COND_V_MSG(buf_info->last_frame_mapped == p_frames_drawn, nullptr, "Buffers with BUFFER_USAGE_DYNAMIC_PERSISTENT_BIT must only be mapped once per frame. Otherwise there could be race conditions with the GPU. Amalgamate all data uploading into one map(), use an extra buffer, or remove the bit."); buf_info->last_frame_mapped = p_frames_drawn; #endif buf_info->frame_idx = (buf_info->frame_idx + 1u) % frame_count; @@ -2296,14 +2296,14 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat & if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) { alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; VkResult err = vmaCreateImage(allocator, &create_info, &alloc_create_info, &vk_image, &allocation, &alloc_info); - ERR_FAIL_COND_V_MSG(err, TextureID(), "vmaCreateImage failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't create Vulkan image in memory for use with extra GPU memory tracking (VkResult error %d).", err)); } else { VkResult err = vkCreateImage(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE), &vk_image); - ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImage failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't create Vulkan image (VkResult error %d).", err)); err = vmaAllocateMemoryForImage(allocator, vk_image, &alloc_create_info, &allocation, &alloc_info); - ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't allocate memory for image, error: " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't allocate memory for Vulkan image (VkResult error %d).", err)); err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, nullptr); - ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't bind memory to image, error: " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't bind memory to Vulkan image (VkResult error %d).", err)); } // Create view. @@ -2345,7 +2345,7 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat & vmaFreeMemory(allocator, allocation); } - ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't create Vulkan image view (VkResult error %d).", err)); } // Bookkeep. @@ -2392,7 +2392,7 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create_from_extension(uint64 VkImageView vk_image_view = VK_NULL_HANDLE; VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view); if (err) { - ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't create Vulkan image view for extension texture (VkResult error %d).", err)); } // Bookkeep. @@ -2447,7 +2447,7 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create_shared(TextureID p_or VkImageView new_vk_image_view = VK_NULL_HANDLE; VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &new_vk_image_view); - ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't create Vulkan image view for shared texture (VkResult error %d).", err)); // Bookkeep. @@ -2500,7 +2500,7 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create_shared_from_slice(Tex VkImageView new_vk_image_view = VK_NULL_HANDLE; VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &new_vk_image_view); - ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, TextureID(), vformat("Couldn't create Vulkan image view for shared texture from slice (VkResult error %d).", err)); // Bookkeep. @@ -2574,7 +2574,7 @@ Vector RenderingDeviceDriverVulkan::texture_get_data(TextureID p_textur void *data_ptr = nullptr; VkResult err = vmaMapMemory(allocator, tex->allocation.handle, &data_ptr); - ERR_FAIL_COND_V_MSG(err, Vector(), "vmaMapMemory failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, Vector(), vformat("Couldn't map Vulkan memory for texture (VkResult error %d).", err)); { uint8_t *w = image_data.ptrw(); @@ -2709,7 +2709,7 @@ RDD::SamplerID RenderingDeviceDriverVulkan::sampler_create(const SamplerState &p VkSampler vk_sampler = VK_NULL_HANDLE; VkResult res = vkCreateSampler(vk_device, &sampler_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SAMPLER), &vk_sampler); - ERR_FAIL_COND_V_MSG(res, SamplerID(), "vkCreateSampler failed with error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, SamplerID(), vformat("Couldn't create Vulkan sampler (VkResult error %d).", res)); return SamplerID(vk_sampler); } @@ -2967,7 +2967,7 @@ RDD::FenceID RenderingDeviceDriverVulkan::fence_create() { VkFenceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; VkResult err = vkCreateFence(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FENCE), &vk_fence); - ERR_FAIL_COND_V(err != VK_SUCCESS, FenceID()); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FenceID(), vformat("Couldn't create Vulkan fence (VkResult error %d).", err)); Fence *fence = memnew(Fence); fence->vk_fence = vk_fence; @@ -2980,11 +2980,11 @@ Error RenderingDeviceDriverVulkan::fence_wait(FenceID p_fence) { VkResult fence_status = vkGetFenceStatus(vk_device, fence->vk_fence); if (fence_status == VK_NOT_READY) { VkResult err = vkWaitForFences(vk_device, 1, &fence->vk_fence, VK_TRUE, UINT64_MAX); - ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FAILED, vformat("Couldn't wait for Vulkan fence (VkResult error %d).", err)); } VkResult err = vkResetFences(vk_device, 1, &fence->vk_fence); - ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FAILED, vformat("Couldn't reset Vulkan fence (VkResult error %d).", err)); if (fence->queue_signaled_from != nullptr) { // Release all semaphores that the command queue associated to the fence waited on the last time it was submitted. @@ -3021,7 +3021,7 @@ RDD::SemaphoreID RenderingDeviceDriverVulkan::semaphore_create() { VkSemaphoreCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; VkResult err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore); - ERR_FAIL_COND_V(err != VK_SUCCESS, SemaphoreID()); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, SemaphoreID(), vformat("Couldn't create Vulkan semaphore (VkResult error %d).", err)); return SemaphoreID(semaphore); } @@ -3087,7 +3087,7 @@ RDD::CommandQueueID RenderingDeviceDriverVulkan::command_queue_create(CommandQue } } - ERR_FAIL_COND_V_MSG(picked_queue_index >= queue_family.size(), CommandQueueID(), "A queue in the picked family could not be found."); + ERR_FAIL_COND_V_MSG(picked_queue_index >= queue_family.size(), CommandQueueID(), "Couldn't find a Vulkan command queue in the picked family."); #if defined(SWAPPY_FRAME_PACING_ENABLED) if (swappy_frame_pacer_enable) { @@ -3150,7 +3150,7 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu pending_flushes.allocations.clear(); pending_flushes.offsets.clear(); pending_flushes.sizes.clear(); - ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FAILED, vformat("Couldn't flush Vulkan memory allocations (VkResult error %d).", err)); } if (p_cmd_buffers.size() > 0) { @@ -3193,9 +3193,9 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu if (err == VK_ERROR_DEVICE_LOST) { print_lost_device_info(); - CRASH_NOW_MSG("Vulkan device was lost."); + CRASH_NOW_MSG("Vulkan device was lost. This could be due to a driver issue, a hardware issue, or the driver resetting itself because it was unresponsive for too long (TDR)."); } - ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FAILED, vformat("Couldn't submit to Vulkan queue (VkResult error %d).", err)); if (fence != nullptr && !command_queue->pending_semaphores_for_fence.is_empty()) { fence->queue_signaled_from = command_queue; @@ -3284,7 +3284,7 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu ERR_FAIL_COND_V_MSG( err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR, FAILED, - "QueuePresentKHR failed with error: " + get_vulkan_result(err)); + "Couldn't present to Vulkan queue (VkResult error " + get_vulkan_result(err) + ")."); } return OK; @@ -3329,7 +3329,7 @@ RDD::CommandPoolID RenderingDeviceDriverVulkan::command_pool_create(CommandQueue VkCommandPool vk_command_pool = VK_NULL_HANDLE; VkResult res = vkCreateCommandPool(vk_device, &cmd_pool_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_COMMAND_POOL), &vk_command_pool); - ERR_FAIL_COND_V_MSG(res, CommandPoolID(), "vkCreateCommandPool failed with error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, CommandPoolID(), vformat("Couldn't create Vulkan command pool (VkResult error %d).", res)); CommandPool *command_pool = memnew(CommandPool); command_pool->vk_command_pool = vk_command_pool; @@ -3342,7 +3342,7 @@ bool RenderingDeviceDriverVulkan::command_pool_reset(CommandPoolID p_cmd_pool) { CommandPool *command_pool = (CommandPool *)(p_cmd_pool.id); VkResult err = vkResetCommandPool(vk_device, command_pool->vk_command_pool, 0); - ERR_FAIL_COND_V_MSG(err, false, "vkResetCommandPool failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, false, vformat("Couldn't reset Vulkan command pool (VkResult error %d).", err)); return true; } @@ -3378,7 +3378,7 @@ RDD::CommandBufferID RenderingDeviceDriverVulkan::command_buffer_create(CommandP VkCommandBuffer vk_command_buffer = VK_NULL_HANDLE; VkResult err = vkAllocateCommandBuffers(vk_device, &cmd_buf_info, &vk_command_buffer); - ERR_FAIL_COND_V_MSG(err, CommandBufferID(), "vkAllocateCommandBuffers failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, CommandBufferID(), vformat("Couldn't allocate Vulkan command buffer (VkResult error %d).", err)); CommandBufferInfo *command_buffer = VersatileResource::allocate(resources_allocator); command_buffer->vk_command_buffer = vk_command_buffer; @@ -3394,7 +3394,7 @@ bool RenderingDeviceDriverVulkan::command_buffer_begin(CommandBufferID p_cmd_buf cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; VkResult err = vkBeginCommandBuffer(command_buffer->vk_command_buffer, &cmd_buf_begin_info); - ERR_FAIL_COND_V_MSG(err, false, "vkBeginCommandBuffer failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, false, vformat("Couldn't begin Vulkan command buffer (VkResult error %d).", err)); return true; } @@ -3416,7 +3416,7 @@ bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID cmd_buf_begin_info.pInheritanceInfo = &inheritance_info; VkResult err = vkBeginCommandBuffer(command_buffer->vk_command_buffer, &cmd_buf_begin_info); - ERR_FAIL_COND_V_MSG(err, false, "vkBeginCommandBuffer failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, false, vformat("Couldn't begin Vulkan command buffer (VkResult error %d).", err)); return true; } @@ -3457,12 +3457,12 @@ bool RenderingDeviceDriverVulkan::_determine_swap_chain_format(RenderingContextD // Retrieve the formats supported by the surface. uint32_t format_count = 0; VkResult err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, nullptr); - ERR_FAIL_COND_V(err != VK_SUCCESS, false); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, false, vformat("Couldn't retrieve Vulkan surface formats (VkResult error %d).", err)); TightLocalVector formats; formats.resize(format_count); err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, formats.ptr()); - ERR_FAIL_COND_V(err != VK_SUCCESS, false); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, false, vformat("Couldn't retrieve Vulkan surface formats (VkResult error %d).", err)); // If the format list includes just one entry of VK_FORMAT_UNDEFINED, the surface has no preferred format. if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) { @@ -3602,14 +3602,14 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get(); if (!context_driver->queue_family_supports_present(physical_device, command_queue->queue_family, swap_chain->surface)) { ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Surface is not supported by device. Did the GPU go offline? Was the window created on another monitor? Check" - "previous errors & try launching with --gpu-validation."); + "previous errors and try launching with --gpu-validation."); } // Retrieve the surface's capabilities. RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(swap_chain->surface); VkSurfaceCapabilitiesKHR surface_capabilities = {}; VkResult err = functions.GetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface->vk_surface, &surface_capabilities); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan surface capabilities (VkResult error %d).", err)); // No swapchain yet, this is the first time we're creating it. if (!swap_chain->vk_swapchain) { @@ -3653,11 +3653,11 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, TightLocalVector present_modes; uint32_t present_modes_count = 0; err = functions.GetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface->vk_surface, &present_modes_count, nullptr); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan surface present modes (VkResult error %d).", err)); present_modes.resize(present_modes_count); err = functions.GetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface->vk_surface, &present_modes_count, present_modes.ptr()); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan surface present modes (VkResult error %d).", err)); // Choose the present mode based on the display server setting. VkPresentModeKHR present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR; @@ -3723,7 +3723,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; RDD::ColorSpace rdd_color_space = COLOR_SPACE_REC709_NONLINEAR_SRGB; if (!_determine_swap_chain_format(swap_chain->surface, format, color_space, rdd_color_space)) { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Surface did not return any valid formats."); + ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Vulkan surface did not return any valid formats."); } else { swap_chain->format = format; swap_chain->color_space = color_space; @@ -3763,7 +3763,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, swap_create_info.presentMode = present_mode; swap_create_info.clipped = true; err = device_functions.CreateSwapchainKHR(vk_device, &swap_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SWAPCHAIN_KHR), &swap_chain->vk_swapchain); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't create Vulkan swapchain (VkResult error %d).", err)); #if defined(SWAPPY_FRAME_PACING_ENABLED) if (swappy_frame_pacer_enable) { @@ -3797,11 +3797,11 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, uint32_t image_count = 0; err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, nullptr); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan swapchain images (VkResult error %d).", err)); swap_chain->images.resize(image_count); err = device_functions.GetSwapchainImagesKHR(vk_device, swap_chain->vk_swapchain, &image_count, swap_chain->images.ptr()); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't get Vulkan swapchain images (VkResult error %d).", err)); VkImageViewCreateInfo view_create_info = {}; view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -3821,7 +3821,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, for (uint32_t i = 0; i < image_count; i++) { view_create_info.image = swap_chain->images[i]; err = vkCreateImageView(vk_device, &view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &image_view); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't create Vulkan image view for swapchain image (VkResult error %d).", err)); swap_chain->image_views.push_back(image_view); } @@ -3859,7 +3859,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, VkRenderPass vk_render_pass = VK_NULL_HANDLE; err = _create_render_pass(vk_device, &pass_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &vk_render_pass); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't create Vulkan render pass for swapchain (VkResult error %d).", err)); RenderPassInfo *render_pass_info = VersatileResource::allocate(resources_allocator); render_pass_info->vk_render_pass = vk_render_pass; @@ -3879,7 +3879,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, for (uint32_t i = 0; i < image_count; i++) { fb_create_info.pAttachments = &swap_chain->image_views[i]; err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer); - ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, ERR_CANT_CREATE, vformat("Couldn't create Vulkan framebuffer for swapchain image (VkResult error %d).", err)); Framebuffer *framebuffer = memnew(Framebuffer); framebuffer->vk_framebuffer = vk_framebuffer; @@ -3894,7 +3894,7 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &vk_semaphore); - ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FAILED, vformat("Couldn't create Vulkan semaphore for swapchain image (VkResult error %d).", err)); swap_chain->present_semaphores.push_back(vk_semaphore); } @@ -3925,7 +3925,7 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(C VkSemaphoreCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore); - ERR_FAIL_COND_V(err != VK_SUCCESS, FramebufferID()); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, FramebufferID(), vformat("Couldn't create Vulkan semaphore for acquiring swapchain image (VkResult error %d).", err)); semaphore_index = command_queue->image_semaphores.size(); command_queue->image_semaphores.push_back(semaphore); @@ -3947,7 +3947,7 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(C if (err == VK_ERROR_OUT_OF_DATE_KHR) { // Out of date leaves the semaphore in a signaled state that will never finish, so it's necessary to recreate it. bool semaphore_recreated = _recreate_image_semaphore(command_queue, semaphore_index, true); - ERR_FAIL_COND_V(!semaphore_recreated, FramebufferID()); + ERR_FAIL_COND_V_MSG(!semaphore_recreated, FramebufferID(), "Couldn't recreate Vulkan semaphore after swapchain becoming out of date."); // Swap chain is out of date and must be recreated. r_resize_required = true; @@ -4058,7 +4058,7 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID VkFramebuffer vk_framebuffer = VK_NULL_HANDLE; VkResult err = vkCreateFramebuffer(vk_device, &framebuffer_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer); - ERR_FAIL_COND_V_MSG(err, FramebufferID(), "vkCreateFramebuffer failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, FramebufferID(), vformat("Couldn't create Vulkan framebuffer (VkResult error %d).", err)); #if PRINT_NATIVE_COMMANDS print_line(vformat("vkCreateFramebuffer 0x%uX with %d attachments", uint64_t(vk_framebuffer), p_attachments.size())); @@ -4341,7 +4341,7 @@ RDD::ShaderID RenderingDeviceDriverVulkan::shader_create_from_container(const Re res = vkCreatePipelineLayout(vk_device, &pipeline_layout_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE_LAYOUT), &shader_info.vk_pipeline_layout); if (res != VK_SUCCESS) { - error_text = vformat("Error (%d) creating pipeline layout.", res); + error_text = vformat("Couldn't create Vulkan pipeline layout (VkResult error %d).", res); } } @@ -4500,7 +4500,7 @@ VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_create(const VkDescriptorPool vk_pool = VK_NULL_HANDLE; VkResult res = vkCreateDescriptorPool(vk_device, &descriptor_set_pool_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL), &vk_pool); if (res) { - ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateDescriptorPool failed with error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, vformat("Couldn't create Vulkan descriptor pool (VkResult error %d).", res)); } return vk_pool; @@ -4790,7 +4790,7 @@ RDD::UniformSetID RenderingDeviceDriverVulkan::uniform_set_create(VectorView RenderingDeviceDriverVulkan::pipeline_cache_serialize() { pipelines_cache.buffer.resize(pipelines_cache.current_size + sizeof(PipelineCacheHeader)); VkResult err = vkGetPipelineCacheData(vk_device, pipelines_cache.vk_cache, &pipelines_cache.current_size, pipelines_cache.buffer.ptrw() + sizeof(PipelineCacheHeader)); - ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_INCOMPLETE, Vector()); // Incomplete is OK because the cache may have grown since the size was queried (unless when exiting). + // Incomplete is OK because the cache may have grown since the size was queried (unless when exiting). + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS && err != VK_INCOMPLETE, Vector(), vformat("Couldn't get Vulkan pipeline cache data (VkResult error %d).", err)); // The real buffer size may now be bigger than the updated current_size. // We take into account the new size but keep the buffer resized in a worst-case fashion. @@ -5403,7 +5404,7 @@ RDD::RenderPassID RenderingDeviceDriverVulkan::render_pass_create(VectorView(resources_allocator); render_pass->vk_render_pass = vk_render_pass; @@ -5771,7 +5772,12 @@ RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create( // Tessellation. VkPipelineTessellationStateCreateInfo tessellation_create_info = {}; tessellation_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; - ERR_FAIL_COND_V(physical_device_properties.limits.maxTessellationPatchSize > 0 && (p_rasterization_state.patch_control_points < 1 || p_rasterization_state.patch_control_points > physical_device_properties.limits.maxTessellationPatchSize), PipelineID()); + ERR_FAIL_COND_V_MSG( + physical_device_properties.limits.maxTessellationPatchSize > 0 && (p_rasterization_state.patch_control_points < 1 || p_rasterization_state.patch_control_points > physical_device_properties.limits.maxTessellationPatchSize), + PipelineID(), + vformat("Invalid Vulkan tessellation patch control point count: %d. It must be between 1 and %d.", + p_rasterization_state.patch_control_points, + physical_device_properties.limits.maxTessellationPatchSize)); tessellation_create_info.patchControlPoints = p_rasterization_state.patch_control_points; // Viewport. @@ -5958,7 +5964,7 @@ RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create( pipeline_create_info.stageCount = shader_info->vk_stages_create_info.size(); ERR_FAIL_COND_V_MSG(pipeline_create_info.stageCount == 0, PipelineID(), - "Cannot create pipeline without shader module, please make sure shader modules are destroyed only after all associated pipelines are created."); + "Can't create Vulkan pipeline without shader module. Make sure shader modules are destroyed only after all associated pipelines are created."); VkPipelineShaderStageCreateInfo *vk_pipeline_stages = ALLOCA_ARRAY(VkPipelineShaderStageCreateInfo, shader_info->vk_stages_create_info.size()); thread_local std::vector respv_optimized_data; @@ -6083,7 +6089,7 @@ RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create( VkPipeline vk_pipeline = VK_NULL_HANDLE; VkResult err = vkCreateGraphicsPipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline); - ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateGraphicsPipelines failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, PipelineID(), vformat("Couldn't create Vulkan graphics pipelines (VkResult error %d).", err)); #if RECORD_PIPELINE_STATISTICS { @@ -6280,7 +6286,7 @@ void RenderingDeviceDriverVulkan::_acceleration_structure_create(VkAccelerationS accel_create_info.size = p_size_info.accelerationStructureSize; accel_create_info.buffer = ((const BufferInfo *)buffer.id)->vk_buffer; VkResult err = vkCreateAccelerationStructureKHR(vk_device, &accel_create_info, nullptr, &r_accel_info->vk_acceleration_structure); - ERR_FAIL_COND_MSG(err, "vkCreateAccelerationStructureKHR failed with error " + itos(err) + "."); + ERR_FAIL_COND_MSG(err, vformat("Couldn't create Vulkan raytracing acceleration structure (VkResult error %d).", err)); r_accel_info->build_info.dstAccelerationStructure = r_accel_info->vk_acceleration_structure; #endif } @@ -6288,7 +6294,7 @@ void RenderingDeviceDriverVulkan::_acceleration_structure_create(VkAccelerationS void RenderingDeviceDriverVulkan::acceleration_structure_free(AccelerationStructureID p_acceleration_structure) { #if VULKAN_RAYTRACING_ENABLED AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id; - ERR_FAIL_NULL_MSG(accel_info, "Acceleration structure input parameter is not valid."); + ERR_FAIL_NULL_MSG(accel_info, "Vulkan raytracing acceleration structure input parameter is not valid."); if (accel_info->buffer) { buffer_free(accel_info->buffer); } @@ -6301,7 +6307,7 @@ void RenderingDeviceDriverVulkan::acceleration_structure_free(AccelerationStruct uint32_t RenderingDeviceDriverVulkan::acceleration_structure_get_scratch_size_bytes(AccelerationStructureID p_acceleration_structure) { AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id; - ERR_FAIL_NULL_V_MSG(accel_info, 0, "Acceleration structure input parameter is not valid."); + ERR_FAIL_NULL_V_MSG(accel_info, 0, "Vulkan raytracing acceleration structure input parameter is not valid."); return accel_info->scratch_size; } @@ -6415,7 +6421,7 @@ RDD::RaytracingPipelineID RenderingDeviceDriverVulkan::raytracing_pipeline_creat } } - ERR_FAIL_COND_V(!found_shader_stage, RaytracingPipelineID()); + ERR_FAIL_COND_V_MSG(!found_shader_stage, RaytracingPipelineID(), vformat("Shader \"%s\" doesn't have a stage compatible with the specified raytracing PipelineShaderStage.", shader_info->name)); } uint32_t shader_group_count = p_raygen_shader_indices.size() + p_miss_shader_indices.size() + p_hit_groups.size(); @@ -6469,7 +6475,7 @@ RDD::RaytracingPipelineID RenderingDeviceDriverVulkan::raytracing_pipeline_creat VkPipeline vk_pipeline = VK_NULL_HANDLE; VkResult err = vkCreateRayTracingPipelinesKHR(vk_device, VK_NULL_HANDLE, pipelines_cache.vk_cache, 1, &pipeline_create_info, nullptr, &vk_pipeline); - ERR_FAIL_COND_V_MSG(err, RaytracingPipelineID(), "vkCreateRayTracingPipelinesKHR failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, RaytracingPipelineID(), vformat("Couldn't create Vulkan raytracing pipelines (VkResult error %d).", err)); return RaytracingPipelineID(vk_pipeline); #else @@ -6485,10 +6491,14 @@ void RenderingDeviceDriverVulkan::raytracing_pipeline_free(RaytracingPipelineID bool RenderingDeviceDriverVulkan::raytracing_pipeline_get_shader_group_handles(RaytracingPipelineID p_pipeline, uint32_t p_group_index_offset, VectorView p_group_indices, uint8_t *r_data, uint32_t p_data_stride_bytes) { #if VULKAN_RAYTRACING_ENABLED - ERR_FAIL_COND_V_MSG(p_data_stride_bytes < raytracing_capabilities.shader_group_handle_size, false, "Data stride must be at least the size of shader group handles."); + ERR_FAIL_COND_V_MSG( + p_data_stride_bytes < raytracing_capabilities.shader_group_handle_size, + false, + vformat("Data stride (%d) must be greater than or equal to the size of the shader group handles (%d).", p_data_stride_bytes, raytracing_capabilities.shader_group_handle_size)); + for (uint32_t i = 0; i < p_group_indices.size(); i++) { VkResult err = vkGetRayTracingShaderGroupHandlesKHR(vk_device, (VkPipeline)p_pipeline.id, p_group_index_offset + p_group_indices[i], 1, raytracing_capabilities.shader_group_handle_size, r_data); - ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, false, "vkGetRayTracingShaderGroupHandlesKHR failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err != VK_SUCCESS, false, vformat("Couldn't get Vulkan raytracing shader group handles (VkResult error %d).", err)); r_data += p_data_stride_bytes; } return true; @@ -6584,7 +6594,7 @@ RDD::PipelineID RenderingDeviceDriverVulkan::compute_pipeline_create(ShaderID p_ VkPipeline vk_pipeline = VK_NULL_HANDLE; VkResult err = vkCreateComputePipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline); - ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateComputePipelines failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, PipelineID(), vformat("Couldn't create Vulkan compute pipelines (VkResult error %d).", err)); return PipelineID(vk_pipeline); }