Commit bea35a63 by Jamie Madill Committed by Commit Bot

Vulkan: Use Scoped resource init helper.

In a few places we initialize resource on the stack in the Vulkan back-end. When we do this we should use a RAII wrapper so that if we generate an error and unwind the stack we can auto-release the object. This fixes a bug that was being triggered by an unexpected failure on Present with the Vulkan back-end on Intel. There are several other places in the code that should be modified to use the new wrapper. Bug: angleproject:2690 Change-Id: I49a1c5516756f8b7dba833aca65926aa7b8bd5c6 Reviewed-on: https://chromium-review.googlesource.com/1118610 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 072c3519
......@@ -180,6 +180,12 @@ RendererVk::CommandBatch &RendererVk::CommandBatch::operator=(CommandBatch &&oth
return *this;
}
void RendererVk::CommandBatch::destroy(VkDevice device)
{
commandPool.destroy(device);
fence.destroy(device);
}
// RendererVk implementation.
RendererVk::RendererVk()
: mCapsInitialized(false),
......@@ -737,7 +743,8 @@ vk::Error RendererVk::submitFrame(const VkSubmitInfo &submitInfo, vk::CommandBuf
fenceInfo.pNext = nullptr;
fenceInfo.flags = 0;
CommandBatch batch;
vk::Scoped<CommandBatch> scopedBatch(mDevice);
CommandBatch &batch = scopedBatch.get();
ANGLE_TRY(batch.fence.init(mDevice, fenceInfo));
ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, batch.fence.getHandle()));
......@@ -746,7 +753,7 @@ vk::Error RendererVk::submitFrame(const VkSubmitInfo &submitInfo, vk::CommandBuf
batch.commandPool = std::move(mCommandPool);
batch.serial = mCurrentQueueSerial;
mInFlightCommands.emplace_back(std::move(batch));
mInFlightCommands.emplace_back(scopedBatch.release());
// Sanity check.
ASSERT(mInFlightCommands.size() < 1000u);
......@@ -818,8 +825,8 @@ vk::Error RendererVk::flush(const gl::Context *context,
const vk::Semaphore &waitSemaphore,
const vk::Semaphore &signalSemaphore)
{
vk::CommandBuffer commandBatch;
ANGLE_TRY(flushCommandGraph(context, &commandBatch));
vk::Scoped<vk::CommandBuffer> commandBatch(mDevice);
ANGLE_TRY(flushCommandGraph(context, &commandBatch.get()));
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
......@@ -830,11 +837,11 @@ vk::Error RendererVk::flush(const gl::Context *context,
submitInfo.pWaitSemaphores = waitSemaphore.ptr();
submitInfo.pWaitDstStageMask = &waitStageMask;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = commandBatch.ptr();
submitInfo.pCommandBuffers = commandBatch.get().ptr();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphore.ptr();
ANGLE_TRY(submitFrame(submitInfo, std::move(commandBatch)));
ANGLE_TRY(submitFrame(submitInfo, commandBatch.release()));
return vk::NoError();
}
......
......@@ -179,6 +179,8 @@ class RendererVk : angle::NonCopyable
CommandBatch(CommandBatch &&other);
CommandBatch &operator=(CommandBatch &&other);
void destroy(VkDevice device);
vk::CommandPool commandPool;
vk::Fence fence;
Serial serial;
......
......@@ -445,6 +445,11 @@ void CommandBuffer::singleBufferBarrier(VkPipelineStageFlags srcStageMask,
&bufferBarrier, 0, nullptr);
}
void CommandBuffer::destroy(VkDevice device)
{
releaseHandle();
}
void CommandBuffer::destroy(VkDevice device, const vk::CommandPool &commandPool)
{
if (valid())
......
......@@ -314,7 +314,13 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
CommandBuffer();
VkCommandBuffer releaseHandle();
// This is used for normal pool allocated command buffers. It reset the handle.
void destroy(VkDevice device);
// This is used in conjunction with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT.
void destroy(VkDevice device, const CommandPool &commandPool);
Error init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
void blitImage(const Image &srcImage,
VkImageLayout srcImageLayout,
......@@ -697,6 +703,25 @@ enum class RecordingMode
Start,
Append,
};
// Helper class to handle RAII patterns for initialization. Requires that T have a destroy method
// that takes a VkDevice and returns void.
template <typename T>
class Scoped final : angle::NonCopyable
{
public:
Scoped(VkDevice device) : mDevice(device) {}
~Scoped() { mVar.destroy(mDevice); }
const T &get() const { return mVar; }
T &get() { return mVar; }
T &&release() { return std::move(mVar); }
private:
VkDevice mDevice;
T mVar;
};
} // 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