首页 > 解决方案 > 在 vulkan 中绘制到帧缓冲区时出现 ioctl 错误

问题描述

我正在为Android 设备编写游戏,如果支持,则使用Android NDKVulkan (否则使用 OpenGL)。我目前正致力于在 Vulkan 中制作阴影。这需要在帧缓冲区中绘制并使用用于绘制到屏幕的着色器中的结果。我注意到,当我使用与交换链图像大小相同的图像的帧缓冲区时,我的速度变慢了很多,并且来自后端驱动程序的错误说:“ioctl ...失败:errno 35 Resource deadlock will occur”。最终我得到一个设备丢失错误(VK_ERROR_DEVICE_LOST)。如果我使用具有交换链图像宽度和高度一半的图像的帧缓冲区,那么一切正常。在所有情况下,我都没有从 Vulkan 验证层得到错误。

在我的游戏中出现设备丢失错误后,我也会在其他应用程序中出现图形损坏。我认为这是个坏消息。我应该不能影响其他正在运行的程序。

错误的全文是:

W/Adreno-GSL: <gsl_ldd_control:549>: ioctl fd 54 code 0x400c0907 (IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID) failed: errno 35 Resource deadlock would occur

有谁知道为什么会发生这种情况?难道我做错了什么?如果它是一个驱动程序错误,关于如何在我的游戏或其他程序中检测它而不导致图形损坏的任何想法?

设备详情:

name: Pixel 4XL phone
Vulkan API version: 1.1.87
Vulkan device name: Adreno (TM) 640
NDK version:  I tried 20.1.5948944 and 21.0.6113669. They both have the problem.
Android version: 10
VkPhysicalDeviceProperties.limits.maxImageDimension2D = 16384
VkPhysicalDeviceProperties.limits.maxFramebufferWidth = 16384
VkPhysicalDeviceProperties.limits.maxFramebufferHeight = 16384
VkSurfaceCapabilitiesKHR.currentExtent.width = 1440
VkSurfaceCapabilitiesKHR.currentExtent.height = 2690
Width of the images in the framebuffer when the problem occurred: 1440
Height of the images in the framebuffer when the problem occurred: 2690

管道是通过以下方式创建的:

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float) VkSurfaceCapabilitiesKHR.currentExtent.width;
viewport.height = (float) VkSurfaceCapabilitiesKHR.currentExtent.height;

帧缓冲区是通过以下方式创建的:

VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = inRenderPass->renderPass().get();
framebufferInfo.attachmentCount = static_cast<uint32_t>(inAttachments.size());
framebufferInfo.pAttachments = inAttachments.data();
framebufferInfo.width = VkSurfaceCapabilitiesKHR.currentExtent.width;
framebufferInfo.height = VkSurfaceCapabilitiesKHR.currentExtent.height;
framebufferInfo.layers = 1;

图像是用以下方式创建的:

VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = VkSurfaceCapabilitiesKHR.currentExtent.width;
imageInfo.extent.height = VkSurfaceCapabilitiesKHR.currentExtent.height;

如果您需要这些结构或其他代码的更多信息,请告诉我。这一切都很长:-)

出现问题时从 android 设备输出:

04/23 21:09:22: Launching 'app' on Google Pixel 4 XL.
$ adb shell am start -n "com.quasar.cerulean.amazinglabyrinth/com.quasar.cerulean.amazinglabyrinth.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Waiting for process to come online...
Connected to process 7507 on device 'google-pixel_4_xl-**************'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
W/mazinglabyrint: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
W/mazinglabyrint: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
I/Adreno: QUALCOMM build                   : 9b214d0, Ibc75db1fca
    Build Date                       : 06/30/19
    OpenGL ES Shader Compiler Version: EV031.26.06.00
    Local Branch                     : AU124
    Remote Branch                    :
    Remote Branch                    :
    Reconstruct Branch               :
    Build Config                     : S P 8.0.6 AArch64
I/Adreno: PFP: 0x016ee185, ME: 0x00000000
D/vulkan: searching for layers in '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64'
D/vulkan: added global layer 'VK_LAYER_LUNARG_parameter_validation' from library '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64/libVkLayer_parameter_validation.so'
D/vulkan: added global layer 'VK_LAYER_KHRONOS_validation' from library '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64/libVkLayer_khronos_validation.so'
D/vulkan: added global layer 'VK_LAYER_GOOGLE_unique_objects' from library '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64/libVkLayer_unique_objects.so'
D/vulkan: added global layer 'VK_LAYER_GOOGLE_threading' from library '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64/libVkLayer_threading.so'
D/vulkan: added global layer 'VK_LAYER_LUNARG_object_tracker' from library '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64/libVkLayer_object_tracker.so'
D/vulkan: added global layer 'VK_LAYER_LUNARG_core_validation' from library '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/lib/arm64/libVkLayer_core_validation.so'
D/vulkan: searching for layers in '/data/app/com.quasar.cerulean.amazinglabyrinth-************************/base.apk!/lib/arm64-v8a'
I/vulkan: Loaded layer VK_LAYER_KHRONOS_validation
I/Adreno: QUALCOMM build          : 9b214d0, Ibc75db1fca
    Build Date              : 06/30/19
    Shader Compiler Version : EV031.26.06.00
    Local Branch            : AU124
    Remote Branch           :
    Remote Branch           :
    Reconstruct Branch      :
    Build Config            : S P 8.0.6 AArch64
E/Looper: Invalid attempt to set NULL callback but not allowed for this looper.
W/Adreno-GSL: <gsl_ldd_control:549>: ioctl fd 54 code 0x400c0907 (IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID) failed: errno 35 Resource deadlock would occur
    <log_gpu_snapshot:458>: panel.gpuSnapshotPath is not set.not generating user snapshot

以下函数用于分配所有图像:

void Image::createImage(VkFormat format, VkImageTiling tiling,
                        VkImageUsageFlags usage,
                        VkMemoryPropertyFlags properties) {

    VkImageCreateInfo imageInfo = {};
    imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    imageInfo.imageType = VK_IMAGE_TYPE_2D;
    imageInfo.extent.width = m_width;
    imageInfo.extent.height = m_height;
    imageInfo.extent.depth = 1;
    imageInfo.mipLevels = 1;
    imageInfo.arrayLayers = 1;

    imageInfo.format = format;
    imageInfo.tiling = tiling;

    imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    imageInfo.usage = usage;
    imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;

    VkImage imageRaw;
    if (vkCreateImage(m_device->logicalDevice().get(), &imageInfo, nullptr, &imageRaw) != VK_SUCCESS) {
        throw std::runtime_error("failed to create image!");
    }

    auto const &capDevice = m_device;
    auto imageDeleter = [capDevice](VkImage imageRaw) {
        vkDestroyImage(capDevice->logicalDevice().get(), imageRaw, nullptr);
    };

    m_image.reset(imageRaw, imageDeleter);

    VkMemoryRequirements memRequirements;
    vkGetImageMemoryRequirements(m_device->logicalDevice().get(), m_image.get(), &memRequirements);

    VkMemoryAllocateInfo allocInfo = {};
    allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    allocInfo.allocationSize = memRequirements.size;
    allocInfo.memoryTypeIndex = m_device->findMemoryType(memRequirements.memoryTypeBits, properties);

    VkDeviceMemory imageMemoryRaw;
    if (vkAllocateMemory(m_device->logicalDevice().get(), &allocInfo, nullptr, &imageMemoryRaw) !=
        VK_SUCCESS) {
        throw std::runtime_error("failed to allocate image memory!");
    }

    auto memoryDeleter = [capDevice](VkDeviceMemory imageMemoryRaw) {
        vkFreeMemory(capDevice->logicalDevice().get(), imageMemoryRaw, nullptr);
    };

    m_imageMemory.reset(imageMemoryRaw, memoryDeleter);

    vkBindImageMemory(m_device->logicalDevice().get(), m_image.get(), m_imageMemory.get(), 0);
}

颜色附件是通过以下方式创建的:

createImage(
   VK_FORMAT_R32G32B32A32_SFLOAT,
   VK_IMAGE_TILING_OPTIMAL,
   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)

m_width = m_swapChain->extent().width;
m_height = m_swapChain->extent().height;

深度附件是通过以下方式创建的:

createImage(
   VK_FORMAT_D32_SFLOAT,
   VK_IMAGE_TILING_OPTIMAL,
   VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)

m_width = m_swapChain->extent().width;
m_height = m_swapChain->extent().height;

标签: androidandroid-ndkvulkan

解决方案


推荐阅读