diff --git a/drape/vulkan/vulkan_gpu_buffer_impl.cpp b/drape/vulkan/vulkan_gpu_buffer_impl.cpp index dc83d65c52..a3caef156b 100644 --- a/drape/vulkan/vulkan_gpu_buffer_impl.cpp +++ b/drape/vulkan/vulkan_gpu_buffer_impl.cpp @@ -14,6 +14,8 @@ VulkanGPUBuffer::VulkanGPUBuffer(ref_ptr context, void const : BufferBase(elementSize, capacity) , m_batcherHash(batcherHash) { + m_regionsToCopy.reserve(5); + m_barriers.reserve(5); Resize(context, data, capacity); } @@ -24,14 +26,14 @@ void * VulkanGPUBuffer::Map(ref_ptr context, uint32_t element VkDevice device = context->GetDevice(); uint32_t const elementSize = GetElementSize(); - m_mappingSizeInBytes = elementCount * elementSize; + uint32_t const mappingSizeInBytes = elementCount * elementSize; m_mappingByteOffset = elementOffset * elementSize; VkCommandBuffer commandBuffer = context->GetCurrentCommandBuffer(); CHECK(commandBuffer != nullptr, ()); // Copy to default or temporary staging buffer. - m_defaultStagingBuffer = m_objectManager->GetDefaultStagingBuffer(m_mappingSizeInBytes); + m_defaultStagingBuffer = m_objectManager->GetDefaultStagingBuffer(mappingSizeInBytes); void * gpuPtr; if (m_defaultStagingBuffer.m_stagingData) { @@ -40,7 +42,7 @@ void * VulkanGPUBuffer::Map(ref_ptr context, uint32_t element else { m_temporaryStagingBuffer = m_objectManager->CreateBuffer(VulkanMemoryManager::ResourceType::Staging, - m_mappingSizeInBytes, 0 /* batcherHash */); + mappingSizeInBytes, 0 /* batcherHash */); CHECK_VK_CALL(vkMapMemory(device, m_temporaryStagingBuffer.m_allocation->m_memory, m_temporaryStagingBuffer.m_allocation->m_alignedOffset, @@ -57,6 +59,26 @@ void VulkanGPUBuffer::UpdateData(void * gpuPtr, void const * data, uint32_t const byteOffset = elementOffset * elementSize; uint32_t const byteCount = elementCount * elementSize; memcpy(static_cast(gpuPtr) + byteOffset, data, byteCount); + + VkBufferCopy copyRegion = {}; + copyRegion.dstOffset = m_mappingByteOffset + byteOffset; + copyRegion.srcOffset = m_defaultStagingBuffer.m_stagingData ? + (m_defaultStagingBuffer.m_stagingData.m_offset + byteOffset) : byteOffset; + copyRegion.size = byteCount; + + VkBufferMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = m_geometryBuffer.m_buffer; + barrier.offset = copyRegion.dstOffset; + barrier.size = copyRegion.size; + + m_regionsToCopy.push_back(std::move(copyRegion)); + m_barriers.push_back(std::move(barrier)); } void VulkanGPUBuffer::Unmap(ref_ptr context) @@ -66,18 +88,14 @@ void VulkanGPUBuffer::Unmap(ref_ptr context) CHECK(commandBuffer != nullptr, ()); VkBuffer stagingBuffer; - uint32_t offset; if (m_defaultStagingBuffer.m_stagingData) { stagingBuffer = m_defaultStagingBuffer.m_stagingData.m_stagingBuffer; - offset = m_defaultStagingBuffer.m_stagingData.m_offset; } else { CHECK(m_temporaryStagingBuffer.m_buffer != 0, ()); - stagingBuffer = m_temporaryStagingBuffer.m_buffer; - offset = 0; VkMappedMemoryRange mappedRange = {}; mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; @@ -92,33 +110,20 @@ void VulkanGPUBuffer::Unmap(ref_ptr context) } // Schedule command to copy from the staging buffer to the geometry buffer. - VkBufferCopy copyRegion = {}; - copyRegion.dstOffset = m_mappingByteOffset; - copyRegion.srcOffset = offset; - copyRegion.size = m_mappingSizeInBytes; - vkCmdCopyBuffer(commandBuffer, stagingBuffer, m_geometryBuffer.m_buffer, - 1, ©Region); + static_cast(m_regionsToCopy.size()), m_regionsToCopy.data()); - // Set up a barrier to prevent data collisions. - VkBufferMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.buffer = m_geometryBuffer.m_buffer; - barrier.offset = m_mappingByteOffset; - barrier.size = m_mappingSizeInBytes; + // Set up barriers to prevent data collisions. vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, - 1, &barrier, 0, nullptr); + static_cast(m_barriers.size()), m_barriers.data(), + 0, nullptr); m_defaultStagingBuffer = {}; m_objectManager->DestroyObject(m_temporaryStagingBuffer); m_mappingByteOffset = 0; - m_mappingSizeInBytes = 0; + m_regionsToCopy.clear(); + m_barriers.clear(); } void VulkanGPUBuffer::Resize(ref_ptr context, void const * data, diff --git a/drape/vulkan/vulkan_gpu_buffer_impl.hpp b/drape/vulkan/vulkan_gpu_buffer_impl.hpp index 045dff9054..62e09ade1b 100644 --- a/drape/vulkan/vulkan_gpu_buffer_impl.hpp +++ b/drape/vulkan/vulkan_gpu_buffer_impl.hpp @@ -13,6 +13,7 @@ #include #include +#include namespace dp { @@ -39,7 +40,8 @@ protected: VulkanObjectManager::StagingPointer m_defaultStagingBuffer; VulkanObject m_temporaryStagingBuffer; uint32_t m_mappingByteOffset = 0; - uint32_t m_mappingSizeInBytes = 0; + std::vector m_regionsToCopy; + std::vector m_barriers; }; class VulkanGpuBufferImpl : public DataBufferImpl