Skip to content

Commit

Permalink
Added last-use tracking for staging buffers on Vulkan to make mapBuff…
Browse files Browse the repository at this point in the history
…er and mapStagingTexture behave the same way they do on DX11/DX12.
  • Loading branch information
apanteleev committed Jul 1, 2022
1 parent 11d0a6d commit cad446c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 27 deletions.
8 changes: 8 additions & 0 deletions src/vulkan/vulkan-backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ namespace nvrhi::vulkan
vk::CommandPool cmdPool = vk::CommandPool();

std::vector<RefCountPtr<IResource>> referencedResources; // to keep them alive
std::vector<RefCountPtr<Buffer>> referencedStagingBuffers; // to allow synchronous mapBuffer

uint64_t recordingID = 0;
uint64_t submissionID = 0;
Expand Down Expand Up @@ -230,6 +231,9 @@ namespace nvrhi::vulkan
CommandQueue getQueueID() const { return m_QueueID; }
vk::Queue getVkQueue() const { return m_Queue; }

bool pollCommandList(uint64_t commandListID);
bool waitCommandList(uint64_t commandListID, uint64_t timeout);

private:
const VulkanContext& m_Context;

Expand Down Expand Up @@ -508,6 +512,10 @@ namespace nvrhi::vulkan
void* mappedMemory = nullptr;
uint32_t versionSearchStart = 0;

// For staging buffers only
CommandQueue lastUseQueue = CommandQueue::Graphics;
uint64_t lastUseCommandListID = 0;

Buffer(const VulkanContext& context, VulkanAllocator& allocator)
: BufferStateExtension(desc)
, m_Context(context)
Expand Down
18 changes: 16 additions & 2 deletions src/vulkan/vulkan-buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,15 @@ namespace nvrhi::vulkan

assert(m_CurrentCmdBuf);

m_CurrentCmdBuf->referencedResources.push_back(dest);
m_CurrentCmdBuf->referencedResources.push_back(src);
if (dest->desc.cpuAccess != CpuAccessMode::None)
m_CurrentCmdBuf->referencedStagingBuffers.push_back(dest);
else
m_CurrentCmdBuf->referencedResources.push_back(dest);

if (src->desc.cpuAccess != CpuAccessMode::None)
m_CurrentCmdBuf->referencedStagingBuffers.push_back(src);
else
m_CurrentCmdBuf->referencedResources.push_back(src);

if (m_EnableAutomaticBarriers)
{
Expand Down Expand Up @@ -502,6 +509,13 @@ namespace nvrhi::vulkan

assert(flags != CpuAccessMode::None);

// If the buffer has been used in a command list before, wait for that CL to complete
if (buffer->lastUseCommandListID != 0)
{
auto& queue = m_Queues[uint32_t(buffer->lastUseQueue)];
queue->waitCommandList(buffer->lastUseCommandListID, ~0ull);
}

vk::AccessFlags accessFlags;

switch(flags)
Expand Down
28 changes: 6 additions & 22 deletions src/vulkan/vulkan-queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,10 @@ namespace nvrhi::vulkan
bool Device::pollEventQuery(IEventQuery* _query)
{
EventQuery* query = checked_cast<EventQuery*>(_query);

if (query->commandListID == 0)
return false;

auto& queue = *m_Queues[uint32_t(query->queue)];
bool completed = queue.getLastFinishedID() >= query->commandListID;
if (completed)
return true;

completed = queue.updateLastFinishedID() >= query->commandListID;
return completed;
auto& queue = *m_Queues[uint32_t(query->queue)];

return queue.pollCommandList(query->commandListID);
}

void Device::waitEventQuery(IEventQuery* _query)
Expand All @@ -65,20 +58,11 @@ namespace nvrhi::vulkan
if (query->commandListID == 0)
return;

if (pollEventQuery(_query))
return;

auto& queue = *m_Queues[uint32_t(query->queue)];
std::array<const vk::Semaphore, 1> semaphores = { queue.trackingSemaphore };
std::array<uint64_t, 1> waitValues = { query->commandListID };

auto waitInfo = vk::SemaphoreWaitInfo()
.setSemaphores(semaphores)
.setValues(waitValues);

vk::Result result = m_Context.device.waitSemaphores(waitInfo, ~0ull);
assert(result == vk::Result::eSuccess); // TODO: add support for limited-time waits
(void)result;
bool success = queue.waitCommandList(query->commandListID, ~0ull);
assert(success);
(void)success;
}

void Device::resetEventQuery(IEventQuery* _query)
Expand Down
45 changes: 42 additions & 3 deletions src/vulkan/vulkan-queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,23 @@ namespace nvrhi::vulkan
waitStageArray[i] = vk::PipelineStageFlagBits::eTopOfPipe;
}

m_LastSubmittedID++;

for (size_t i = 0; i < numCmd; i++)
{
CommandList* commandList = checked_cast<CommandList*>(ppCmd[i]);
TrackedCommandBufferPtr commandBuffer = commandList->getCurrentCmdBuf();

commandBuffers[i] = commandBuffer->cmdBuf;
m_CommandBuffersInFlight.push_back(commandBuffer);
}

m_LastSubmittedID++;

for (const auto& buffer : commandBuffer->referencedStagingBuffers)
{
buffer->lastUseQueue = m_QueueID;
buffer->lastUseCommandListID = m_LastSubmittedID;
}
}

m_SignalSemaphores.push_back(trackingSemaphore);
m_SignalSemaphoreValues.push_back(m_LastSubmittedID);

Expand Down Expand Up @@ -189,6 +195,7 @@ namespace nvrhi::vulkan
if (cmd->submissionID <= lastFinishedID)
{
cmd->referencedResources.clear();
cmd->referencedStagingBuffers.clear();
cmd->submissionID = 0;
m_CommandBuffersPool.push_back(cmd);

Expand Down Expand Up @@ -258,4 +265,36 @@ namespace nvrhi::vulkan
return m_Context.device.getSemaphoreCounterValue(getQueueSemaphore(queue));
}

bool Queue::pollCommandList(uint64_t commandListID)
{
if (commandListID > m_LastSubmittedID || commandListID == 0)
return false;

bool completed = getLastFinishedID() >= commandListID;
if (completed)
return true;

completed = updateLastFinishedID() >= commandListID;
return completed;
}

bool Queue::waitCommandList(uint64_t commandListID, uint64_t timeout)
{
if (commandListID > m_LastSubmittedID || commandListID == 0)
return false;

if (pollCommandList(commandListID))
return true;

std::array<const vk::Semaphore, 1> semaphores = { trackingSemaphore };
std::array<uint64_t, 1> waitValues = { commandListID };

auto waitInfo = vk::SemaphoreWaitInfo()
.setSemaphores(semaphores)
.setValues(waitValues);

vk::Result result = m_Context.device.waitSemaphores(waitInfo, timeout);

return (result == vk::Result::eSuccess);
}
} // namespace nvrhi::vulkan
5 changes: 5 additions & 0 deletions src/vulkan/vulkan-staging-texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ namespace nvrhi::vulkan
}
commitBarriers();

m_CurrentCmdBuf->referencedResources.push_back(src);
m_CurrentCmdBuf->referencedResources.push_back(dst);
m_CurrentCmdBuf->referencedStagingBuffers.push_back(dst->buffer);

m_CurrentCmdBuf->cmdBuf.copyImageToBuffer(src->image, vk::ImageLayout::eTransferSrcOptimal,
dst->buffer->buffer, 1, &imageCopy);
}
Expand Down Expand Up @@ -261,6 +265,7 @@ namespace nvrhi::vulkan

m_CurrentCmdBuf->referencedResources.push_back(src);
m_CurrentCmdBuf->referencedResources.push_back(dst);
m_CurrentCmdBuf->referencedStagingBuffers.push_back(src->buffer);

m_CurrentCmdBuf->cmdBuf.copyBufferToImage(src->buffer->buffer,
dst->image, vk::ImageLayout::eTransferDstOptimal,
Expand Down

0 comments on commit cad446c

Please sign in to comment.