c++ - Vulkan 中绘制调用之间的同步

标签 c++ vulkan

据我所知,如果我有一个 drawcall 以某种方式使用任何先前 drawcall 的结果或写入相同的渲染目标(帧缓冲区),那么我需要确保后面的 drawcall 看到内存效果所有之前的绘图调用。

但是,当我渲染一个包含一堆对象的场景时,每个这样的对象都是一个绘制调用,所有这些绘制调用都写入同一个帧缓冲区。

我是否需要在每次绘制调用后发出内存屏障?

例如 Sascha Willem 的 pbrbasic 示例有这段代码(有点简化),我在那里没有看到任何管道障碍:

VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));

vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);

VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);

VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);

VkDeviceSize offsets[1] = { 0 };

vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &models.objects[models.objectIndex].vertices.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], models.objects[models.objectIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32);

Material mat = materials[materialIndex];

for (uint32_t y = 0; y < GRID_DIM; y++) {
    for (uint32_t x = 0; x < GRID_DIM; x++) {
        glm::vec3 pos = glm::vec3(float(x - (GRID_DIM / 2.0f)) * 2.5f, 0.0f, float(y - (GRID_DIM / 2.0f)) * 2.5f);
        vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos);
        mat.params.metallic = glm::clamp((float)x / (float)(GRID_DIM - 1), 0.1f, 1.0f);
        mat.params.roughness = glm::clamp((float)y / (float)(GRID_DIM - 1), 0.05f, 1.0f);
        vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(glm::vec3), sizeof(Material::PushBlock), &mat);
        vkCmdDrawIndexed(drawCmdBuffers[i], models.objects[models.objectIndex].indexCount, 1, 0, 0, 0);
    }
}

drawUI(drawCmdBuffers[i]);

vkCmdEndRenderPass(drawCmdBuffers[i]);

VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));

是否可以保证逻辑上跟在后面的绘制调用会看到逻辑上在它们之前的绘制调用的内存效应?

所以问题是,我什么时候需要在不同的绘制调用之间进行同步?

最佳答案

uses the results of any previous drawcall or writes to the same render target

它们是一回事。就同​​步而言,渲染操作的副作用(您通过图像加载/存储或 SSBO 修改的内容)和写入帧缓冲区的内容有非常不同的需求。

导致将值写入帧缓冲区的固定函数操作(剪刀测试、深度测试、混合等)由 rasterization order 管理。 :它们必须以原子方式并以特定顺序发生,在给定的原语中并且对于可能写入帧缓冲区的特定样本。并且此类操作的执行也必须尊重primitive order :绘图命令生成的图元顺序,以及绘图命令图元的顺序。

就渲染而言,绘制调用将尊重同一子 channel 内先前绘制调用的结果(子 channel 之间由显式子 channel 依赖性控制)。您不需要做任何特别的事情来进行混合。如果你有两个重叠的三角形,一个按原始顺序发生在另一个之后,则第二次绘制的混合将使用第一次绘制的结果。它只是工作。

您的着色器的任何其他写入都需要显式同步。

关于c++ - Vulkan 中绘制调用之间的同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56849788/

相关文章:

c++ - 错误 : request for member (maybe you meant to use '->' ? ) 已经使用 '->'

c++ - C++ 中的 OpenGL - 运行时崩溃

windows - Vulkan 中如何确定曲面的大小?

opengl - 自动为 Vulkan 编译 OpenGL 着色器

specifications - 创建子 channel 时什么时候应该使用 VK_ATTACHMENT_UNUSED?

c++ - 从多重继承中确定模板包

c++ - boost 互斥锁的作用域解锁

c++ - Qt5部署 "procedure entry point could not be located"

glsl - Vulkan中的实例化GLSL着色器?

android-studio - Android Studio - 启动模拟器出错 - Vulkan-1.dll