Мой вопрос состоит из 2 частей:
- В чем разница между доступной / видимой памятью?
Я изучаю Vulkan по этому руководству (https://vulkan-tutorial.com) и сейчас крадусь в поисках другого подход для загрузки унифицированных данных (простых матриц модели / вида / проекции) в локальную память устройства. Матрицы используются в вершинном шейдере.
В этом руководстве матрицы обновляются и копируются в промежуточный буфер (
vkMapMemory
и т. Д.), А затем копируются в конечный локальный буфер устройства путем создания командного буфера, записиvkCmdCopy
, отправки и уничтожения буфера. Я стараюсь сделать последний шаг в пределах обязательных командных буферов для рисования.Хотя учебный метод приводит к плавной анимации, в моем эксперименте эта функция отсутствует. Я попытался установить 2 bufferBarrier, чтобы гарантировать, что копии сделаны (что кажется проблемой), но это не помогло. Ресурсы правильно созданы и привязаны - все работает нормально.
//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 заключалась в отсутствии синхронизации; Промежуточный буфер был (частично) обновлен до того, как он был прочитан во время рендеринга кадра ранее. (Спасибо, что разъяснили разницу между доступной / видимой памятью).
vkFreeCommandBuffers
. Поскольку это код из учебного пособия, выбран самый простой способ, а не лучший. - person camelCase   schedule 14.11.2016