渲染循环中无需重建命令缓冲区,能否更新Push Constant值?
关于Vulkan Push Constant与Command Buffer更新的问题
首先明确结论:已录制完成的Command Buffer无法修改其中的Push Constant值,你必须在渲染循环中重新生成包含更新后旋转值的Command Buffer。
原因很简单:Vulkan的Command Buffer一旦结束录制(脱离VK_COMMAND_BUFFER_STATE_RECORDING状态),内部所有命令(包括vkCmdPushConstants调用的参数)都会被固化成不可修改的二进制数据。你之前创建的3个Command Buffer在录制时就把当时的旋转值写入了Push Constant,后续自然无法再更改这个值。
针对你的场景,正确的做法是将Command Buffer的录制逻辑整合到渲染循环中:
- 每帧先更新游戏对象的旋转值
- 重置当前帧可用的Command Buffer并重新进入录制状态
- 录制时将最新的旋转值计算后写入Push Constant,再完成后续绑定、绘制命令
- 结束录制后提交Command Buffer执行
调整后的逻辑示例(伪代码):
// 渲染循环内 for each frame { // 重置Command Buffer到可录制状态 vkResetCommandBuffer(commandBuffer, 0); VkCommandBufferBeginInfo beginInfo = {}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; vkBeginCommandBuffer(commandBuffer, &beginInfo); // 开始渲染流程 mypipeline->bind(commandBuffer); for (auto& obj : gameObjects) { // 更新旋转值 obj.transform2d.rotation = glm::mod(obj.transform2d.rotation + 0.05f, glm::two_pi<float>()); // 构造最新的Push Constant数据 simplepushconstantdata push{}; push.offset = obj.transform2d.translation; push.color = obj.color; push.transform = obj.transform2d.mat2(); // 写入最新的Push Constant vkCmdPushConstants(commandBuffer, mypipelinelayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(simplepushconstantdata), &push); obj.model->bind(commandBuffer); obj.model->draw(commandBuffer); } // 结束Command Buffer录制 vkEndCommandBuffer(commandBuffer); // 提交Command Buffer到队列执行 // ... 提交逻辑 ... }
如果想优化录制开销,可以把管线绑定、模型绑定这类固定操作提前录制到二级Command Buffer中复用,每帧只录制包含最新Push Constant和绘制调用的一级Command Buffer,再通过一级Command Buffer调用二级Command Buffer,核心逻辑还是要每帧录制包含更新后Push Constant的命令部分。
内容的提问来源于stack exchange,提问作者fresh bird
相关产品推荐
相关产品推荐

