【发布时间】:2019-07-24 04:11:24
【问题描述】:
据我了解,如果我有一个 drawcall 以某种方式使用任何以前的 drawcall 的结果或写入相同的渲染目标(帧缓冲区),那么我需要确保后面的 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]));
是否有任何保证,在逻辑上之后的绘制调用会看到逻辑上在它们之前的绘制调用的内存效应?
所以问题是,我什么时候需要在不同的drawcalls之间进行同步?
【问题讨论】:
-
你指的是哪种记忆效应?在另一个绘制之后执行绘制基本上是 Write-After-Write 操作并由硬件处理(例如深度缓冲区,混合顺序)。但是在第一次绘制写入之后的第二次绘制读取的情况下,您需要以某种方式同步(不确定在同一个队列提交期间是否可能)。