Vulkan项目Release模式下createPipelineInfo初始化函数被编译器优化问题
问题根本原因
你遇到的不是函数调用被优化掉的问题,而是典型的悬垂指针问题:
createPipelineInfo的第一个参数shaderStages使用值传递,调用时会复制出一份函数内的局部临时数组对象- 你给
pipelineInfo.pStages赋值的是这个局部数组的内存指针shaderStages.data() - 函数返回后局部临时数组生命周期结束,对应栈内存会被编译器回收复用,
pipelineInfo.pStages就变成了悬空指针 - Debug模式下栈内存回收后不会立即被覆写,指针指向的内容暂时有效,所以程序能正常运行;Release模式下编译器会优化栈内存的复用,悬空指针指向的内容被篡改,最终导致
vkCreateGraphicsPipelines调用失败。
你把函数体直接复制到调用位置能正常运行,是因为此时shaderStages是调用栈上的对象,生命周期覆盖到vkCreateGraphicsPipelines调用完成,指针不会悬空。
解决方案
不需要复制函数体,最简单的修复方法如下:
- 修改
createPipelineInfo的第一个参数类型为常量左值引用,避免产生函数内的局部数组复制:
// 把原来的值传递参数改为引用传递 inline static VkGraphicsPipelineCreateInfo createPipelineInfo( const std::array<VkPipelineShaderStageCreateInfo, 2>& shaderStages, // 仅此处新增&即可 const VkPipelineVertexInputStateCreateInfo& vertexInputInfo, const VkPipelineInputAssemblyStateCreateInfo& inputAssembly, const VkPipelineViewportStateCreateInfo& viewportState, const VkPipelineRasterizationStateCreateInfo& rasterizer, const VkPipelineMultisampleStateCreateInfo& multisampling, const VkPipelineColorBlendStateCreateInfo& colorBlending, const VkPipelineLayout& pipelineLayout, const VkRenderPass& renderPass) { // 函数内部实现无需修改 }
修改后pipelineInfo.pStages指向的是调用方传入的原数组对象,只要保证原数组的生命周期覆盖到vkCreateGraphicsPipelines调用完成即可正常运行。
如果需要长期持有pipeline创建信息,可以自定义包装结构体,把VkGraphicsPipelineCreateInfo和所有它引用的状态对象(shaderStages、vertexInputInfo等)都作为结构体成员,保证所有引用指向的内存生命周期一致。
内容的提问来源于stack exchange,提问作者Ryoku
相关产品推荐
相关产品推荐

