Commit 7f738d4e by Jamie Madill Committed by Commit Bot

Vulkan: Refactor CommandBuffer helper class.

This makes the base vk::CommandBuffer class as close to the Vulkan API as possible. It moves the extra functionality and state tracking to a CommandBufferAndState helper class. Also no longer stores a reference to a CommandPool in a CommandBuffer. Eventually we won't need to free CommandBuffers explicitly, since they can be freed en-masse by deallocating the CommandPool on a flush. Bug: angleproject:2200 Change-Id: I5095fe89e8da935ff8273b1a402ccfd6a3ffe0df Reviewed-on: https://chromium-review.googlesource.com/778184Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 4f407ce2
......@@ -194,7 +194,7 @@ vk::Error BufferVk::setDataImpl(ContextVk *contextVk,
// TODO(jmadill): Command re-ordering for render passes.
renderer->endRenderPass();
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(renderer->getStartedCommandBuffer(&commandBuffer));
// Insert a barrier to ensure reads from the buffer are complete.
......
......@@ -323,7 +323,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, GLenum mode)
angle::MemoryBuffer *zeroBuf = nullptr;
ANGLE_TRY(context->getZeroFilledBuffer(maxAttrib * sizeof(VkDeviceSize), &zeroBuf));
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer));
ANGLE_TRY(mRenderer->ensureInRenderPass(context, vkFBO));
......@@ -360,7 +360,7 @@ gl::Error ContextVk::drawArrays(const gl::Context *context, GLenum mode, GLint f
{
ANGLE_TRY(setupDraw(context, mode));
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer));
commandBuffer->draw(count, 1, first, 0);
......@@ -399,7 +399,7 @@ gl::Error ContextVk::drawElements(const gl::Context *context,
return gl::InternalError() << "Unsigned byte translation is not yet implemented.";
}
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer));
const gl::Buffer *elementArrayBuffer =
......@@ -441,12 +441,12 @@ VkDevice ContextVk::getDevice() const
return mRenderer->getDevice();
}
vk::Error ContextVk::getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut)
vk::Error ContextVk::getStartedCommandBuffer(vk::CommandBufferAndState **commandBufferOut)
{
return mRenderer->getStartedCommandBuffer(commandBufferOut);
}
vk::Error ContextVk::submitCommands(vk::CommandBuffer *commandBuffer)
vk::Error ContextVk::submitCommands(vk::CommandBufferAndState *commandBuffer)
{
setQueueSerial(mRenderer->getCurrentQueueSerial());
ANGLE_TRY(mRenderer->submitCommandBuffer(commandBuffer));
......
......@@ -137,8 +137,8 @@ class ContextVk : public ContextImpl, public ResourceVk
std::vector<PathImpl *> createPaths(GLsizei) override;
VkDevice getDevice() const;
vk::Error getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut);
vk::Error submitCommands(vk::CommandBuffer *commandBuffer);
vk::Error getStartedCommandBuffer(vk::CommandBufferAndState **commandBufferOut);
vk::Error submitCommands(vk::CommandBufferAndState *commandBuffer);
RendererVk *getRenderer() { return mRenderer; }
......
......@@ -170,7 +170,7 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
const auto &size = attachment->getSize();
const gl::Rectangle renderArea(0, 0, size.width, size.height);
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(contextVk->getStartedCommandBuffer(&commandBuffer));
for (const auto &colorAttachment : mState.getColorAttachments())
......@@ -276,7 +276,7 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
renderTarget->extents, vk::StagingUsage::Read,
&stagingImage));
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(contextVk->getStartedCommandBuffer(&commandBuffer));
// End render pass if we're in one.
......
......@@ -120,7 +120,7 @@ RendererVk::~RendererVk()
if (mCommandBuffer.valid())
{
mCommandBuffer.destroy(mDevice);
mCommandBuffer.destroy(mDevice, mCommandPool);
}
if (mCommandPool.valid())
......@@ -429,8 +429,6 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
ANGLE_TRY(mCommandPool.init(mDevice, commandPoolInfo));
mCommandBuffer.setCommandPool(&mCommandPool);
return vk::NoError();
}
......@@ -569,16 +567,16 @@ const gl::Limitations &RendererVk::getNativeLimitations() const
return mNativeLimitations;
}
vk::Error RendererVk::getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut)
vk::Error RendererVk::getStartedCommandBuffer(vk::CommandBufferAndState **commandBufferOut)
{
ANGLE_TRY(mCommandBuffer.begin(mDevice));
ANGLE_TRY(mCommandBuffer.ensureStarted(mDevice, mCommandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
*commandBufferOut = &mCommandBuffer;
return vk::NoError();
}
vk::Error RendererVk::submitCommandBuffer(vk::CommandBuffer *commandBuffer)
vk::Error RendererVk::submitCommandBuffer(vk::CommandBufferAndState *commandBuffer)
{
ANGLE_TRY(commandBuffer->end());
ANGLE_TRY(commandBuffer->ensureFinished());
VkFenceCreateInfo fenceInfo;
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
......@@ -602,7 +600,7 @@ vk::Error RendererVk::submitCommandBuffer(vk::CommandBuffer *commandBuffer)
return vk::NoError();
}
vk::Error RendererVk::submitAndFinishCommandBuffer(vk::CommandBuffer *commandBuffer)
vk::Error RendererVk::submitAndFinishCommandBuffer(vk::CommandBufferAndState *commandBuffer)
{
ANGLE_TRY(submitCommandBuffer(commandBuffer));
ANGLE_TRY(finish());
......@@ -610,7 +608,7 @@ vk::Error RendererVk::submitAndFinishCommandBuffer(vk::CommandBuffer *commandBuf
return vk::NoError();
}
vk::Error RendererVk::submitCommandsWithSync(vk::CommandBuffer *commandBuffer,
vk::Error RendererVk::submitCommandsWithSync(vk::CommandBufferAndState *commandBuffer,
const vk::Semaphore &waitSemaphore,
const vk::Semaphore &signalSemaphore)
{
......@@ -647,13 +645,13 @@ void RendererVk::freeAllInFlightResources()
{
for (auto &fence : mInFlightFences)
{
fence.destroy(mDevice);
fence.get().destroy(mDevice);
}
mInFlightFences.clear();
for (auto &command : mInFlightCommands)
{
command.destroy(mDevice);
command.get().destroy(mDevice, mCommandPool);
}
mInFlightCommands.clear();
......@@ -681,7 +679,7 @@ vk::Error RendererVk::checkInFlightCommands()
// Release the fence handle.
// TODO(jmadill): Re-use fences.
inFlightFence->destroy(mDevice);
inFlightFence->get().destroy(mDevice);
}
if (finishedIndex == 0)
......@@ -698,7 +696,7 @@ vk::Error RendererVk::checkInFlightCommands()
break;
completedCBIndex = cbIndex + 1;
inFlightCB->destroy(mDevice);
inFlightCB->get().destroy(mDevice, mCommandPool);
}
if (completedCBIndex == 0)
......
......@@ -52,10 +52,10 @@ class RendererVk : angle::NonCopyable
vk::ErrorOrResult<uint32_t> selectPresentQueueForSurface(VkSurfaceKHR surface);
// TODO(jmadill): Use ContextImpl for command buffers to enable threaded contexts.
vk::Error getStartedCommandBuffer(vk::CommandBuffer **commandBufferOut);
vk::Error submitCommandBuffer(vk::CommandBuffer *commandBuffer);
vk::Error submitAndFinishCommandBuffer(vk::CommandBuffer *commandBuffer);
vk::Error submitCommandsWithSync(vk::CommandBuffer *commandBuffer,
vk::Error getStartedCommandBuffer(vk::CommandBufferAndState **commandBufferOut);
vk::Error submitCommandBuffer(vk::CommandBufferAndState *commandBuffer);
vk::Error submitAndFinishCommandBuffer(vk::CommandBufferAndState *commandBuffer);
vk::Error submitCommandsWithSync(vk::CommandBufferAndState *commandBuffer,
const vk::Semaphore &waitSemaphore,
const vk::Semaphore &signalSemaphore);
vk::Error finish();
......@@ -144,7 +144,7 @@ class RendererVk : angle::NonCopyable
uint32_t mCurrentQueueFamilyIndex;
VkDevice mDevice;
vk::CommandPool mCommandPool;
vk::CommandBuffer mCommandBuffer;
vk::CommandBufferAndState mCommandBuffer;
GlslangWrapper *mGlslangWrapper;
SerialFactory mQueueSerialFactory;
Serial mLastCompletedQueueSerial;
......
......@@ -356,7 +356,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
ANGLE_VK_TRY(vkGetSwapchainImagesKHR(device, mSwapchain, &imageCount, swapchainImages.data()));
// CommandBuffer is a singleton in the Renderer.
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(renderer->getStartedCommandBuffer(&commandBuffer));
VkClearColorValue transparentBlack;
......@@ -423,7 +423,7 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context)
const DisplayVk *displayVk = vk::GetImpl(context->getCurrentDisplay());
RendererVk *renderer = displayVk->getRenderer();
vk::CommandBuffer *currentCB = nullptr;
vk::CommandBufferAndState *currentCB = nullptr;
ANGLE_TRY(renderer->getStartedCommandBuffer(&currentCB));
// End render pass
......
......@@ -227,7 +227,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
stagingImage.getDeviceMemory().unmap(device);
vk::CommandBuffer *commandBuffer = nullptr;
vk::CommandBufferAndState *commandBuffer = nullptr;
ANGLE_TRY(contextVk->getStartedCommandBuffer(&commandBuffer));
setQueueSerial(renderer->getCurrentQueueSerial());
......
......@@ -272,57 +272,19 @@ Error CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createIn
}
// CommandBuffer implementation.
CommandBuffer::CommandBuffer() : mStarted(false), mCommandPool(nullptr)
CommandBuffer::CommandBuffer()
{
}
void CommandBuffer::setCommandPool(CommandPool *commandPool)
Error CommandBuffer::begin(const VkCommandBufferBeginInfo &info)
{
ASSERT(!mCommandPool && commandPool->valid());
mCommandPool = commandPool;
}
Error CommandBuffer::begin(VkDevice device)
{
if (mStarted)
{
return NoError();
}
if (mHandle == VK_NULL_HANDLE)
{
VkCommandBufferAllocateInfo commandBufferInfo;
commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
commandBufferInfo.pNext = nullptr;
commandBufferInfo.commandPool = mCommandPool->getHandle();
commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
commandBufferInfo.commandBufferCount = 1;
ANGLE_VK_TRY(vkAllocateCommandBuffers(device, &commandBufferInfo, &mHandle));
}
else
{
reset();
}
mStarted = true;
VkCommandBufferBeginInfo beginInfo;
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.pNext = nullptr;
// TODO(jmadill): Use other flags?
beginInfo.flags = 0;
beginInfo.pInheritanceInfo = nullptr;
ANGLE_VK_TRY(vkBeginCommandBuffer(mHandle, &beginInfo));
ASSERT(valid());
ANGLE_VK_TRY(vkBeginCommandBuffer(mHandle, &info));
return NoError();
}
Error CommandBuffer::end()
{
mStarted = false;
ASSERT(valid());
ANGLE_VK_TRY(vkEndCommandBuffer(mHandle));
return NoError();
......@@ -330,8 +292,6 @@ Error CommandBuffer::end()
Error CommandBuffer::reset()
{
mStarted = false;
ASSERT(valid());
ANGLE_VK_TRY(vkResetCommandBuffer(mHandle, 0));
return NoError();
......@@ -357,16 +317,23 @@ void CommandBuffer::singleBufferBarrier(VkPipelineStageFlags srcStageMask,
&bufferBarrier, 0, nullptr);
}
void CommandBuffer::destroy(VkDevice device)
void CommandBuffer::destroy(VkDevice device, const vk::CommandPool &commandPool)
{
if (valid())
{
ASSERT(mCommandPool && mCommandPool->valid());
vkFreeCommandBuffers(device, mCommandPool->getHandle(), 1, &mHandle);
ASSERT(commandPool.valid());
vkFreeCommandBuffers(device, commandPool.getHandle(), 1, &mHandle);
mHandle = VK_NULL_HANDLE;
}
}
Error CommandBuffer::init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo)
{
ASSERT(!valid());
ANGLE_VK_TRY(vkAllocateCommandBuffers(device, &createInfo, &mHandle));
return NoError();
}
void CommandBuffer::copyBuffer(const vk::Buffer &srcBuffer,
const vk::Buffer &destBuffer,
uint32_t regionCount,
......@@ -1234,6 +1201,58 @@ void GarbageObject::destroy(VkDevice device)
}
}
// CommandBufferAndState implementation.
CommandBufferAndState::CommandBufferAndState() : mStarted(false)
{
}
Error CommandBufferAndState::ensureStarted(VkDevice device,
const vk::CommandPool &commandPool,
VkCommandBufferLevel level)
{
ASSERT(commandPool.valid());
if (valid() && mStarted)
{
return NoError();
}
if (!valid())
{
VkCommandBufferAllocateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
createInfo.pNext = nullptr;
createInfo.commandPool = commandPool.getHandle();
createInfo.level = level;
createInfo.commandBufferCount = 1;
ANGLE_TRY(init(device, createInfo));
}
else
{
reset();
}
VkCommandBufferBeginInfo beginInfo;
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.pNext = nullptr;
// TODO(jmadill): Use other flags?
beginInfo.flags = 0;
beginInfo.pInheritanceInfo = nullptr;
ANGLE_TRY(begin(beginInfo));
mStarted = true;
return NoError();
}
Error CommandBufferAndState::ensureFinished()
{
ANGLE_TRY(end());
mStarted = false;
return NoError();
}
} // namespace vk
namespace gl_vk
......
......@@ -304,18 +304,17 @@ class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
};
// Helper class that wraps a Vulkan command buffer.
class CommandBuffer final : public WrappedObject<CommandBuffer, VkCommandBuffer>
class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
{
public:
CommandBuffer();
bool started() const { return mStarted; }
void destroy(VkDevice device);
void destroy(VkDevice device, const vk::CommandPool &commandPool);
Error init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
using WrappedObject::operator=;
void setCommandPool(CommandPool *commandPool);
Error begin(VkDevice device);
Error begin(const VkCommandBufferBeginInfo &info);
Error end();
Error reset();
......@@ -376,10 +375,6 @@ class CommandBuffer final : public WrappedObject<CommandBuffer, VkCommandBuffer>
const VkDescriptorSet *descriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t *dynamicOffsets);
private:
bool mStarted;
CommandPool *mCommandPool;
};
class Image final : public WrappedObject<Image, VkImage>
......@@ -627,20 +622,16 @@ class ObjectAndSerial final : angle::NonCopyable
return *this;
}
void destroy(VkDevice device) { mObject.destroy(device); }
Serial queueSerial() const { return mQueueSerial; }
const ObjT &get() const { return mObject; }
ObjT &get() { return mObject; }
private:
ObjT mObject;
Serial mQueueSerial;
};
using CommandBufferAndSerial = ObjectAndSerial<CommandBuffer>;
using FenceAndSerial = ObjectAndSerial<Fence>;
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
const VkMemoryRequirements &requirements,
uint32_t propertyFlagMask);
......@@ -657,6 +648,25 @@ struct BufferAndMemory final : private angle::NonCopyable
vk::DeviceMemory memory;
};
class CommandBufferAndState : public vk::CommandBuffer
{
public:
CommandBufferAndState();
Error ensureStarted(VkDevice device,
const vk::CommandPool &commandPool,
VkCommandBufferLevel level);
Error ensureFinished();
bool started() const { return mStarted; }
private:
bool mStarted;
};
using CommandBufferAndSerial = ObjectAndSerial<CommandBufferAndState>;
using FenceAndSerial = ObjectAndSerial<Fence>;
} // namespace vk
namespace gl_vk
......
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