【发布时间】:2025-12-13 03:50:02
【问题描述】:
我的问题分为两部分:
- 内存可用/可见之间有什么区别?
-
我正在从本教程 (https://vulkan-tutorial.com) 中学习 Vulkan,目前正在寻找一种不同的方法来将统一数据(简单模型/视图/投影矩阵)上传到设备本地内存。矩阵用于顶点着色器。
在教程中,矩阵得到更新并被复制到暂存缓冲区(
vkMapMemory等),然后通过创建命令缓冲区、记录vkCmdCopy、提交并销毁缓冲。我尝试在绘图的强制性命令缓冲区中执行最后一步。虽然教程的方式可以带来流畅的动画,但我的实验错过了这个功能。我尝试安装 2 个 bufferBarriers 以确保完成副本(这似乎是问题),但这并没有帮助。资源已正确创建和绑定 - 运行良好。
//update uniform buffer and copy it to the staging buffer //(called every frame) Tools::UniformBufferObject ubo; //set the matrices void* data; data = device.mapMemory( uniformStagingMemory, 0, sizeof( ubo ), (vk::MemoryMapFlagBits) 0 ); memcpy( data, &ubo, sizeof( ubo )); device.unmapMemory( uniformStagingMemory ); //once: create a command buffer for each framebuffer of the swapchain //queueFamily struct members set properly //1st barrier: make transfer from host memory to staging buffer available / visible vk::BufferMemoryBarrier bufMemBarrierStaging; bufMemBarrierStaging.srcAccessMask = vk::AccessFlagBits::eHostWrite; bufMemBarrierStaging.dstAccessMask = vk::AccessFlagBits::eTransferRead; bufMemBarrierStaging.buffer = uniformStagingBuffer; bufMemBarrierStaging.offset = 0; bufMemBarrierStaging.size = sizeof( Tools::UniformBufferObject ); //2nd barrier: make transfer from staging buffer to device local buffer available / visible vk::BufferMemoryBarrier bufMemBarrier; bufMemBarrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; bufMemBarrier.dstAccessMask = vk::AccessFlagBits::eUniformRead | vk::AccessFlagBits::eShaderRead; bufMemBarrier.buffer = dataBuffer; bufMemBarrier.offset = dataBufferOffsets[2]; bufMemBarrier.size = sizeof( Tools::UniformBufferObject ); for( size_t i = 0; i < cmdBuffers.size(); i++ ) { //begin command buffer cmdBuffers[i].pipelineBarrier( vk::PipelineStageFlagBits::eHost, //srcPipelineStage vk::PipelineStageFlagBits::eTransfer, //dstPipelineStage (vk::DependencyFlagBits) 0, nullptr, //memBarrier bufMemBarrierStaging, nullptr //imgBarrier ); vk::BufferCopy copyRegion; //filled appropriate cmdBuffers[i].copyBuffer( uniformStagingBuffer, dataBuffer, copyRegion ); cmdBuffers[i].pipelineBarrier( vk::PipelineStageFlagBits::eTransfer, //srcPipelineStage vk::PipelineStageFlagBits::eVertexShader, //dstPipelineStage (vk::DependencyFlagBits) 0, nullptr, //memBarrier bufMemBarrier, nullptr //imgBarrier ); //renderpass stuff and drawing etc. }与
namespace Tools { struct UniformBufferObject { glm::mat4 model; glm::mat4 view; glm::mat4 proj; }; }; vk::Buffer uniformStagingBuffer; vk::DeviceMemory uniformStagingMemory; //dataBuffer also contains the vertex and index data, is device local vk::Buffer dataBuffer; vk::DeviceMemory dataBufferMemory; vk::vector<vk::DeviceSize> dataBufferOffsets; std::vector<vk::CommandBuffer> cmdBuffers;我正在使用
vkcpp(https://github.com/KhronosGroup/Vulkan-Hpp)。这种非流体动画缺少数据连贯性的原因是 - 我试图实现这一点是否有误?
提前致谢!
编辑:第 2 部分的问题是缺少同步;在渲染之前的帧期间读取暂存缓冲区之前(部分)更新了暂存缓冲区。 (感谢您明确内存可用/可见之间的区别)。
【问题讨论】:
-
“内存可用/可见之间有什么区别?”不清楚你所说的“可用”是什么意思。 “并销毁缓冲区” 为什么要销毁缓冲区?你到底是什么意思?
-
顺便说一句,您不需要第一个内存屏障。内存屏障HOST_WRITE_BIT / HOST_STAGE是通过command buffer的提交隐式完成的。
-
@NicolBolas 第一个问题是指规范的第 6.4 节,关于内存依赖的段落。我看不出有什么区别。破坏缓冲区意味着,我调用
vkFreeCommandBuffers。由于这是教程中的代码,因此选择了最简单的方法,而不是好的方法。