繁体   English   中英

Vulkan中的调用之间的同步

[英]Synchronization between drawcalls in Vulkan

据我了解,如果我有一个通过某种方式使用任何先前调用的结果或写入同一渲染目标(帧缓冲区)的调用,那么我需要确保后面的调用能够看到所有先前调用的内存效果drawcalls。

但是,当我用一堆对象渲染场景时,每个这样的对象都是一个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]));

是否有任何保证可以确保逻辑上之后的调用在逻辑上先于调用之后的记忆效果?

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

使用以前的任何绘画调用的结果或写入相同的渲染目标

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

导致将值写入帧缓冲区的固定功能操作(剪刀测试,深度测试,混合等)由光栅化顺序控制 :它们必须在给定的原语中并针对特定的对象,以原子方式并以该特定顺序发生。样本可能被写入帧缓冲区。 和这样的操作的执行也必须尊重原始顺序 :由绘图命令产生的图元的顺序,但也原语的一个绘图命令的顺序。

因此,就渲染而言,绘图调用将尊重同一子通道内先前绘图调用的结果(子通道之间由显式子通道依赖项控制)。 您无需执行任何特殊操作即可进行混合。 如果您有两个重叠的三角形,一个三角形按照原始顺序在另一个三角形之后发生,则第二个绘制的混合将使用第一个绘制的结果。 它只是工作。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM