android - 在 vulkan 中绘制到帧缓冲区时出现 ioctl 错误
问题描述
我正在为Android 设备编写游戏,如果支持,则使用Android NDK和Vulkan (否则使用 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;
解决方案
推荐阅读
- google-cloud-platform - 为什么 Cloud Functions 的身份验证与 Cloud Endpoints 不同?
- javascript - Lodash 合并:仅在源值与目标值匹配时复制对象属性
- javascript - 节点 FetchError:无效的 json 响应正文 - JSON 中的意外令牌 <
- vmware - VMware api获取带有虚拟机ID的快照列表
- excel - 在 MS Excel 中使用子字符串查找字符串的单元格索引
- javascript - 如何在不离开当前页面的情况下创建点击通话按钮?
- ansible - 当我执行 Ansible playbook 时,apt update 和 upgrade 总是失败
- sqlite - 当按下发送按钮时,想要在屏幕上的文本字段中显示带有文本的卡片列表
- gradle - 使用 Grade、Jacoco 和 Sonarqube 处理多项目构建
- javascript - 组件更新后解决一个承诺