【问题标题】:How to debug VK_ERROR_DEVICE_LOST from calling vkCmdTraceRaysNV?如何通过调用 vkCmdTraceRaysNV 来调试 VK_ERROR_DEVICE_LOST?
【发布时间】:2021-02-28 22:26:44
【问题描述】:

我正在开发一个 vulkan 光线追踪应用程序,但我有点卡住了。一切似乎都正常,直到我调用 vkCmdTraceRaysNV 并将其记录到我的命令缓冲区中,应用程序崩溃并在 vkQueueSubmit 中返回 VK_ERROR_DEVICE_LOST 异常。我检查了 Nvidia NSight 中的基本内容,纹理似乎正确,加速结构也正确可视化。标准验证层什么也没提供。我认为它要么与着色器绑定表有关,要么以奇怪的顺序执行命令缓冲区的内容。除了看代码,还有其他的验证方式吗?

这是命令缓冲区的内容,也许有人知道whatsup(如果我将 vkCmdTraceRaysNV 注释掉它不会崩溃):

VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(extent.width);
viewport.height = static_cast<float>(extent.height);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = extent;

VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass;
renderPassInfo.framebuffer = framebuffers[framebufferIndex];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = extent;

std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { 0.0f, 0.0f, 0.0f, 1.0f };
clearValues[1].depthStencil = { 1.0f, 0 };

renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();

// begin normal vertex rendering
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

VkBuffer vertexBuffers[] = { vertexBuffer };
VkDeviceSize offset[] = { 0 };

vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offset);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(commandBuffer, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);

for (const auto& object : objects) {
    vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &object.model);
    vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(object.indices.size()), 1, object.indexOffset, object.vertexOffset, 0);
}

vkCmdEndRenderPass(commandBuffer);

// acquire textures for ray tracing use
ImageMemoryBarrier(cmdBuffer, depthTexture.image, VK_IMAGE_ASPECT_DEPTH_BIT, 
    0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);

ImageMemoryBarrier(cmdBuffer, shadowsTexture.image, VK_IMAGE_ASPECT_COLOR_BIT,
    0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);

// bind the pipeline and resources
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipeline);
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdPushConstants(cmdBuffer, pipelineLayout, VK_SHADER_STAGE_RAYGEN_BIT_NV, 0, sizeof(pushData), &pushData);

// calculate SBT
VkDeviceSize progSize = rtProps.shaderGroupBaseAlignment;  // Size of a program identifier
VkDeviceSize rayGenOffset   = 0u * progSize;  // Start at the beginning of m_sbtBuffer
VkDeviceSize missOffset     = 1u * progSize;  // Jump over raygen
VkDeviceSize missStride     = progSize;

// run ray tracing, this is where it crashes
vk_nv_ray_tracing::vkCmdTraceRaysNV(cmdBuffer, 
     sbtBuffer, rayGenOffset, // raygen group 
     sbtBuffer, missOffset, missStride, // miss group
     VK_NULL_HANDLE, 0, 0, 
     VK_NULL_HANDLE, 0, 0, 
     width, height, 1
);

着色器绑定表代码:

/// define the groups, a miss group and raygen group
VkRayTracingShaderGroupCreateInfoNV group = {};
group.generalShader         = 0;
group.anyHitShader          = VK_SHADER_UNUSED_NV;
group.closestHitShader      = VK_SHADER_UNUSED_NV;
group.intersectionShader    = VK_SHADER_UNUSED_NV;
group.sType                 = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
group.type                  = VkRayTracingShaderGroupTypeNV::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV;

groups.push_back(group);
group.generalShader = 1;
groups.push_back(group);

const uint32_t groupCount = static_cast<uint32_t>(groups.size());
const uint32_t sbtSize = groupCount * rtProps.shaderGroupBaseAlignment;
std::vector<uint8_t> shaderHandles(sbtSize);

if (vk_nv_ray_tracing::vkGetRayTracingShaderGroupHandlesNV(device, pipeline, 0, groupCount, sbtSize, shaderHandles.data()) != VK_SUCCESS) {
        throw std::runtime_error("failed to get rt shader group handles");
    }

VkBufferCreateInfo sbtBufferCreateInfo = {};
sbtBufferCreateInfo.size = sbtSize;
sbtBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
sbtBufferCreateInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
sbtBufferCreateInfo.usage = VkBufferUsageFlagBits::VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;

VmaAllocationCreateInfo sbtBufferAllocInfo = {};
sbtBufferAllocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
sbtBufferAllocInfo.flags = VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT;

VmaAllocationInfo allocInfo{};

if (vmaCreateBuffer(allocator, &sbtBufferCreateInfo, &sbtBufferAllocInfo, &sbtBuffer, &sbtAlloc, &allocInfo) != VK_SUCCESS) {
        throw std::runtime_error("failed to create sbt buffer");
}

auto* pData = reinterpret_cast<uint8_t*>(allocInfo.pMappedData);
for (uint32_t g = 0; g < groupCount; g++) {
    std::memcpy(pData, groups.data() + g * rtProps.shaderGroupHandleSize, rtProps.shaderGroupHandleSize);
    pData += rtProps.shaderGroupBaseAlignment;
}

【问题讨论】:

  • 根据我的经验,使用 RT 时提交命令缓冲区时崩溃通常表明加速结构设置存在问题。例如。为暂存缓冲区使用错误的内存类型,过早释放内存等。所以它会
  • @SaschaWillems Vulkan 霸主本人! :D 在 NSight 中,底层和顶层加速结构都可以正确显示(它只是一个立方体),并且禁用了深度复制,所以我认为它们没问题?
  • 我仍然会检查正确的使用位,尤其是。对于暂存缓冲区。如果您可以排除 AS,请检查您的着色器绑定表,并确保您已将正确的着色器句柄从管道复制到 SBT。

标签: c++ vulkan raytracing


【解决方案1】:

我遇到了同样的问题。即使我没有创建加速结构,也没有绑定数据,它仍然返回 VK_ERROR_DEVICE_LOST 并且在 VK_NV_device_diagnostic_checkpoints 中报告了 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT

在我的例子中,着色器绑定表的大小及其复制方式存在问题。

【讨论】:

  • 我一定会检查 VK_NV_device_diagnostic_checkpoints 扩展以进行调试,谢谢!我还将 SBT 代码添加到帖子中,也许有一些明显的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多