【问题标题】:Compiler "Optimizes" Out Object Initialization Function编译器“优化”出对象初始化函数
【发布时间】:2021-07-31 09:10:27
【问题描述】:

我有一个需要在使用之前填充的对象,名为 pipelineInfo。为了填充对象,我使用了一个名为 createPipelineInfo 的函数。这在我使用 Visual Studio 编译调试版本时非常有效,但是当我尝试编译发布版本时,编译器会“优化”整个 createPipelineInfo 函数。

这是初始化对象的调用及其用途:

VkGraphicsPipelineCreateInfo pipelineInfo = createPipelineInfo(shaderStages, vertexInputInfo, inputAssembly, viewportState, rasterizer,
    multisampling, colorBlending, pipelineLayout, renderPass);

if (vkCreateGraphicsPipelines(logicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
    throw std::runtime_error("failed to create graphics pipeline!");
}

以下是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) {

    VkGraphicsPipelineCreateInfo pipelineInfo{};

    //Shader Stage
    pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
    pipelineInfo.stageCount = 2;
    pipelineInfo.pStages = shaderStages.data();

    //Fixed Pipeline Stage
    pipelineInfo.pVertexInputState = &vertexInputInfo;
    pipelineInfo.pInputAssemblyState = &inputAssembly;
    pipelineInfo.pViewportState = &viewportState;
    pipelineInfo.pRasterizationState = &rasterizer;
    pipelineInfo.pMultisampleState = &multisampling;
    //pipelineInfo.pDepthStencilState = &depthStencil;
    pipelineInfo.pColorBlendState = &colorBlending;
    pipelineInfo.pDynamicState = nullptr; // Optional

    //Pipeline Layout
    pipelineInfo.layout = pipelineLayout;
    pipelineInfo.renderPass = renderPass;
    pipelineInfo.subpass = 0;
    pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;

    return pipelineInfo;
}

另一方面,如果我复制函数的主体并将其转储以代替函数调用,则一切正常。

VkGraphicsPipelineCreateInfo pipelineInfo{};

//Shader Stage
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages.data();

//Fixed Pipeline Stage
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
//pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = nullptr; // Optional

//Pipeline Layout
pipelineInfo.layout = pipelineLayout;
pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;


if (vkCreateGraphicsPipelines(logicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
    throw std::runtime_error("failed to create graphics pipeline!");
}

我试图弄清楚为什么编译器会优化函数调用,而试图开发一种不涉及转储函数体来代替对函数的每次调用的解决方法却失败了。

【问题讨论】:

    标签: c++ visual-studio compiler-optimization vulkan release-builds


    【解决方案1】:

    胡乱猜测:这个参数是copy传递的

    const std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages
    

    所以当在这里使用data方法调用获取其内容的地址时:

    pipelineInfo.pStages = shaderStages.data();
    

    你调用未定义的行为。编译器不够聪明,无法 1) 由于调用的复杂性,警告您不要引用临时文件,以及 2) 它不会在参数传递时自动执行复制省略。

    修复:通过引用传递它(注意所有其他参数使用按引用模式是有原因的)

    const std::array<VkPipelineShaderStageCreateInfo, 2> &shaderStages
    

    【讨论】:

    • 哇,你完全做到了!并且非常快,谢谢。我通过引用传递所有内容以尝试更明确地使用我的代码,因为如果它们是常量,则在将它们传递给函数时不需要浪费循环复制值,并且我忘记通过引用传递需要它的参数大多数。
    猜你喜欢
    • 2015-01-11
    • 1970-01-01
    • 2015-05-13
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多