Commit f651c773 by Jamie Madill Committed by Commit Bot

Vulkan: Enable command queueing.

This adds the ability for rendering to happen asynchronously. If objects in-use are deleted as they are being accessed, ownership is transferred to the Renderer and they are deleted when not in use. We determine they're ready for delete using a Fence object. BUG=angleproject:1898 Change-Id: I4fcfd90ad0665d127bf01a10214a604f3407d9e4 Reviewed-on: https://chromium-review.googlesource.com/428353Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent a5527071
...@@ -280,7 +280,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -280,7 +280,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
ANGLE_TRY(commandBuffer->end()); ANGLE_TRY(commandBuffer->end());
ANGLE_TRY(mRenderer->submitAndFinishCommandBuffer(*commandBuffer)); ANGLE_TRY(mRenderer->submitCommandBuffer(*commandBuffer));
return gl::NoError(); return gl::NoError();
} }
...@@ -338,8 +338,7 @@ vk::CommandBuffer *ContextVk::getCommandBuffer() ...@@ -338,8 +338,7 @@ vk::CommandBuffer *ContextVk::getCommandBuffer()
vk::Error ContextVk::submitCommands(const vk::CommandBuffer &commandBuffer) vk::Error ContextVk::submitCommands(const vk::CommandBuffer &commandBuffer)
{ {
// TODO(jmadill): Command queuing. ANGLE_TRY(mRenderer->submitCommandBuffer(commandBuffer));
ANGLE_TRY(mRenderer->submitAndFinishCommandBuffer(commandBuffer));
return vk::NoError(); return vk::NoError();
} }
......
...@@ -322,8 +322,10 @@ gl::Error FramebufferVk::readPixels(ContextImpl *context, ...@@ -322,8 +322,10 @@ gl::Error FramebufferVk::readPixels(ContextImpl *context,
PackPixels(params, angleFormat, inputPitch, mapPointer, reinterpret_cast<uint8_t *>(pixels)); PackPixels(params, angleFormat, inputPitch, mapPointer, reinterpret_cast<uint8_t *>(pixels));
stagingImage.getImage().destroy(renderer->getDevice());
stagingImage.getDeviceMemory().unmap(device); stagingImage.getDeviceMemory().unmap(device);
renderer->enqueueGarbage(renderer->getCurrentQueueSerial(), std::move(stagingImage));
stagingImage.getImage().destroy(renderer->getDevice());
stagingImage.destroy(device); stagingImage.destroy(device);
......
...@@ -576,7 +576,7 @@ vk::CommandBuffer *RendererVk::getCommandBuffer() ...@@ -576,7 +576,7 @@ vk::CommandBuffer *RendererVk::getCommandBuffer()
return &mCommandBuffer; return &mCommandBuffer;
} }
vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer) vk::Error RendererVk::submitCommandBuffer(const vk::CommandBuffer &commandBuffer)
{ {
VkFenceCreateInfo fenceInfo; VkFenceCreateInfo fenceInfo;
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
...@@ -599,7 +599,12 @@ vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &comm ...@@ -599,7 +599,12 @@ vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &comm
// TODO(jmadill): Investigate how to properly submit command buffers. // TODO(jmadill): Investigate how to properly submit command buffers.
ANGLE_TRY(submit(submitInfo)); ANGLE_TRY(submit(submitInfo));
// Wait indefinitely for the queue to finish. return vk::NoError();
}
vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer)
{
ANGLE_TRY(submitCommandBuffer(commandBuffer));
ANGLE_TRY(finish()); ANGLE_TRY(finish());
return vk::NoError(); return vk::NoError();
...@@ -635,13 +640,15 @@ vk::Error RendererVk::waitThenFinishCommandBuffer(const vk::CommandBuffer &comma ...@@ -635,13 +640,15 @@ vk::Error RendererVk::waitThenFinishCommandBuffer(const vk::CommandBuffer &comma
vk::Error RendererVk::finish() vk::Error RendererVk::finish()
{ {
ASSERT(mQueue != VK_NULL_HANDLE); ASSERT(mQueue != VK_NULL_HANDLE);
checkInFlightCommands();
ANGLE_VK_TRY(vkQueueWaitIdle(mQueue)); ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
checkInFlightCommands();
return vk::NoError(); return vk::NoError();
} }
vk::Error RendererVk::checkInFlightCommands() vk::Error RendererVk::checkInFlightCommands()
{ {
bool anyFinished = false;
// Check if any in-flight command buffers are finished. // Check if any in-flight command buffers are finished.
for (size_t index = 0; index < mInFlightCommands.size();) for (size_t index = 0; index < mInFlightCommands.size();)
{ {
...@@ -655,6 +662,7 @@ vk::Error RendererVk::checkInFlightCommands() ...@@ -655,6 +662,7 @@ vk::Error RendererVk::checkInFlightCommands()
mLastCompletedQueueSerial = inFlightCommand->queueSerial(); mLastCompletedQueueSerial = inFlightCommand->queueSerial();
inFlightCommand->destroy(mDevice); inFlightCommand->destroy(mDevice);
mInFlightCommands.erase(mInFlightCommands.begin() + index); mInFlightCommands.erase(mInFlightCommands.begin() + index);
anyFinished = true;
} }
else else
{ {
...@@ -662,6 +670,22 @@ vk::Error RendererVk::checkInFlightCommands() ...@@ -662,6 +670,22 @@ vk::Error RendererVk::checkInFlightCommands()
} }
} }
if (anyFinished)
{
size_t freeIndex = 0;
for (; freeIndex < mGarbage.size(); ++freeIndex)
{
if (!mGarbage[freeIndex]->destroyIfComplete(mDevice, mLastCompletedQueueSerial))
break;
}
// Remove the entries from the garbage list - they should be ready to go.
if (freeIndex > 0)
{
mGarbage.erase(mGarbage.begin(), mGarbage.begin() + freeIndex);
}
}
return vk::NoError(); return vk::NoError();
} }
......
...@@ -51,6 +51,7 @@ class RendererVk : angle::NonCopyable ...@@ -51,6 +51,7 @@ class RendererVk : angle::NonCopyable
// TODO(jmadill): Use ContextImpl for command buffers to enable threaded contexts. // TODO(jmadill): Use ContextImpl for command buffers to enable threaded contexts.
vk::CommandBuffer *getCommandBuffer(); vk::CommandBuffer *getCommandBuffer();
vk::Error submitCommandBuffer(const vk::CommandBuffer &commandBuffer);
vk::Error submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer); vk::Error submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer);
vk::Error waitThenFinishCommandBuffer(const vk::CommandBuffer &commandBuffer, vk::Error waitThenFinishCommandBuffer(const vk::CommandBuffer &commandBuffer,
const vk::Semaphore &waitSemaphore); const vk::Semaphore &waitSemaphore);
...@@ -70,6 +71,13 @@ class RendererVk : angle::NonCopyable ...@@ -70,6 +71,13 @@ class RendererVk : angle::NonCopyable
Serial getCurrentQueueSerial() const; Serial getCurrentQueueSerial() const;
template <typename T>
void enqueueGarbage(Serial serial, T &&object)
{
mGarbage.emplace_back(std::unique_ptr<vk::GarbageObject<T>>(
new vk::GarbageObject<T>(serial, std::move(object))));
}
private: private:
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
void generateCaps(gl::Caps *outCaps, void generateCaps(gl::Caps *outCaps,
...@@ -103,6 +111,7 @@ class RendererVk : angle::NonCopyable ...@@ -103,6 +111,7 @@ class RendererVk : angle::NonCopyable
Serial mCurrentQueueSerial; Serial mCurrentQueueSerial;
Serial mLastCompletedQueueSerial; Serial mLastCompletedQueueSerial;
std::vector<vk::FenceAndCommandBuffer> mInFlightCommands; std::vector<vk::FenceAndCommandBuffer> mInFlightCommands;
std::vector<std::unique_ptr<vk::IGarbageObject>> mGarbage;
}; };
} // namespace rx } // namespace rx
......
...@@ -664,6 +664,14 @@ StagingImage::StagingImage() : mSize(0) ...@@ -664,6 +664,14 @@ StagingImage::StagingImage() : mSize(0)
{ {
} }
StagingImage::StagingImage(StagingImage &&other)
: mImage(std::move(other.mImage)),
mDeviceMemory(std::move(other.mDeviceMemory)),
mSize(other.mSize)
{
other.mSize = 0;
}
void StagingImage::destroy(VkDevice device) void StagingImage::destroy(VkDevice device)
{ {
mImage.destroy(device); mImage.destroy(device);
......
...@@ -342,6 +342,7 @@ class StagingImage final : angle::NonCopyable ...@@ -342,6 +342,7 @@ class StagingImage final : angle::NonCopyable
{ {
public: public:
StagingImage(); StagingImage();
StagingImage(StagingImage &&other);
void destroy(VkDevice device); void destroy(VkDevice device);
void retain(VkDevice device, StagingImage &&other); void retain(VkDevice device, StagingImage &&other);
...@@ -441,6 +442,34 @@ class FenceAndCommandBuffer final : angle::NonCopyable ...@@ -441,6 +442,34 @@ class FenceAndCommandBuffer final : angle::NonCopyable
CommandBuffer mCommandBuffer; CommandBuffer mCommandBuffer;
}; };
class IGarbageObject : angle::NonCopyable
{
public:
virtual bool destroyIfComplete(VkDevice device, Serial completedSerial) = 0;
};
template <typename T>
class GarbageObject final : public IGarbageObject
{
public:
GarbageObject(Serial serial, T &&object) : mSerial(serial), mObject(std::move(object)) {}
bool destroyIfComplete(VkDevice device, Serial completedSerial) override
{
if (completedSerial >= mSerial)
{
mObject.destroy(device);
return true;
}
return false;
}
private:
Serial mSerial;
T mObject;
};
} // namespace vk } // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps, Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment