Commit b540da89 by Jamie Madill Committed by Commit Bot

Vulkan: Use ResourceUse to track object lifetime.

With the new resource tracking scheme the CommandGraph, tracking a "Context serial" aka "current" serial is no longer necessary for CommandGraphResources. Serial tracking has been moved to the shared ResourceUse struct that gets updated on a command submission. Thus we don't need to store the serial as a current separate piece of info in BufferHelper/ImageHelper. Will lead to further redesign for the multi-threading support for Vulkan. Bug: angleproject:2464 Change-Id: I1ae4bcc27fcfb93422b4ab4c9682a458e482f295 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1785990 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 01f7e545
...@@ -222,7 +222,7 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, ...@@ -222,7 +222,7 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
ANGLE_TRY(contextVk->flushImpl(nullptr)); ANGLE_TRY(contextVk->flushImpl(nullptr));
} }
// Make sure the GPU is done with the buffer. // Make sure the GPU is done with the buffer.
ANGLE_TRY(contextVk->finishToSerial(mBuffer.getStoredQueueSerial())); ANGLE_TRY(contextVk->finishToSerial(mBuffer.getLatestSerial()));
ASSERT(!mBuffer.isResourceInUse(contextVk)); ASSERT(!mBuffer.isResourceInUse(contextVk));
} }
...@@ -319,7 +319,7 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk, ...@@ -319,7 +319,7 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk,
VK_ACCESS_HOST_WRITE_BIT, copyRegion)); VK_ACCESS_HOST_WRITE_BIT, copyRegion));
// Immediately release staging buffer. We should probably be using a DynamicBuffer here. // Immediately release staging buffer. We should probably be using a DynamicBuffer here.
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &stagingBuffer); contextVk->addGarbage(&stagingBuffer);
} }
else else
{ {
......
...@@ -255,17 +255,10 @@ bool CommandGraphResource::isResourceInUse(ContextVk *contextVk) const ...@@ -255,17 +255,10 @@ bool CommandGraphResource::isResourceInUse(ContextVk *contextVk) const
return mUse.getCounter() > 1 || contextVk->isSerialInUse(mUse.getSerial()); return mUse.getCounter() > 1 || contextVk->isSerialInUse(mUse.getSerial());
} }
void CommandGraphResource::resetQueueSerial()
{
mCurrentWritingNode = nullptr;
mCurrentReadingNodes.clear();
mUse.resetSerial();
}
angle::Result CommandGraphResource::recordCommands(ContextVk *context, angle::Result CommandGraphResource::recordCommands(ContextVk *context,
CommandBuffer **commandBufferOut) CommandBuffer **commandBufferOut)
{ {
onGraphAccess(context->getCurrentQueueSerial(), context->getCommandGraph()); onGraphAccess(context->getCommandGraph());
if (!hasChildlessWritingNode() || hasStartedRenderPass()) if (!hasChildlessWritingNode() || hasStartedRenderPass())
{ {
...@@ -323,7 +316,7 @@ void CommandGraphResource::addWriteDependency(ContextVk *contextVk, ...@@ -323,7 +316,7 @@ void CommandGraphResource::addWriteDependency(ContextVk *contextVk,
void CommandGraphResource::addReadDependency(ContextVk *contextVk, void CommandGraphResource::addReadDependency(ContextVk *contextVk,
CommandGraphResource *readingResource) CommandGraphResource *readingResource)
{ {
onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); onGraphAccess(contextVk->getCommandGraph());
CommandGraphNode *readingNode = readingResource->mCurrentWritingNode; CommandGraphNode *readingNode = readingResource->mCurrentWritingNode;
ASSERT(readingNode); ASSERT(readingNode);
...@@ -353,7 +346,7 @@ void CommandGraphResource::startNewCommands(ContextVk *contextVk) ...@@ -353,7 +346,7 @@ void CommandGraphResource::startNewCommands(ContextVk *contextVk)
void CommandGraphResource::onWriteImpl(ContextVk *contextVk, CommandGraphNode *writingNode) void CommandGraphResource::onWriteImpl(ContextVk *contextVk, CommandGraphNode *writingNode)
{ {
onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); onGraphAccess(contextVk->getCommandGraph());
// Make sure any open reads and writes finish before we execute 'writingNode'. // Make sure any open reads and writes finish before we execute 'writingNode'.
if (!mCurrentReadingNodes.empty()) if (!mCurrentReadingNodes.empty())
......
...@@ -339,19 +339,6 @@ class SharedResourceUse final : angle::NonCopyable ...@@ -339,19 +339,6 @@ class SharedResourceUse final : angle::NonCopyable
return mUse->serial; return mUse->serial;
} }
ANGLE_INLINE void updateSerial(Serial serial)
{
ASSERT(valid());
ASSERT(mUse->serial < serial);
mUse->serial = serial;
}
ANGLE_INLINE void resetSerial()
{
ASSERT(valid());
mUse->serial = Serial();
}
ANGLE_INLINE uint32_t getCounter() const ANGLE_INLINE uint32_t getCounter() const
{ {
ASSERT(valid()); ASSERT(valid());
...@@ -376,9 +363,8 @@ class CommandGraphResource : angle::NonCopyable ...@@ -376,9 +363,8 @@ class CommandGraphResource : angle::NonCopyable
// Returns true if the resource is in use by the renderer. // Returns true if the resource is in use by the renderer.
bool isResourceInUse(ContextVk *contextVk) const; bool isResourceInUse(ContextVk *contextVk) const;
// Get the current queue serial for this resource. Used to release resources, and for
// queries, to know if the queue they are submitted on has finished execution. // queries, to know if the queue they are submitted on has finished execution.
Serial getStoredQueueSerial() const { return mUse.getSerial(); } Serial getLatestSerial() const { return mUse.getSerial(); }
// Sets up dependency relations. 'this' resource is the resource being written to. // Sets up dependency relations. 'this' resource is the resource being written to.
void addWriteDependency(ContextVk *contextVk, CommandGraphResource *writingResource); void addWriteDependency(ContextVk *contextVk, CommandGraphResource *writingResource);
...@@ -388,12 +374,7 @@ class CommandGraphResource : angle::NonCopyable ...@@ -388,12 +374,7 @@ class CommandGraphResource : angle::NonCopyable
// Updates the in-use serial tracked for this resource. Will clear dependencies if the resource // Updates the in-use serial tracked for this resource. Will clear dependencies if the resource
// was not used in this set of command nodes. // was not used in this set of command nodes.
// TODO(jmadill): Remove serial once migrated. http://angelbug.com/2464 void onGraphAccess(CommandGraph *commandGraph);
void onGraphAccess(Serial serial, CommandGraph *commandGraph);
// Reset the current queue serial for this resource. Will clear dependencies if the resource
// was not used in this set of command nodes.
void resetQueueSerial();
// Allocates a write node via getNewWriteNode and returns a started command buffer. // Allocates a write node via getNewWriteNode and returns a started command buffer.
// The started command buffer will render outside of a RenderPass. // The started command buffer will render outside of a RenderPass.
...@@ -415,8 +396,7 @@ class CommandGraphResource : angle::NonCopyable ...@@ -415,8 +396,7 @@ class CommandGraphResource : angle::NonCopyable
// Checks if we're in a RenderPass that encompasses renderArea, returning true if so. Updates // Checks if we're in a RenderPass that encompasses renderArea, returning true if so. Updates
// serial internally. Returns the started command buffer in commandBufferOut. // serial internally. Returns the started command buffer in commandBufferOut.
bool appendToStartedRenderPass(Serial serial, bool appendToStartedRenderPass(CommandGraph *graph,
CommandGraph *graph,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
CommandBuffer **commandBufferOut); CommandBuffer **commandBufferOut);
...@@ -601,25 +581,24 @@ ANGLE_INLINE bool CommandGraphResource::hasStartedRenderPass() const ...@@ -601,25 +581,24 @@ ANGLE_INLINE bool CommandGraphResource::hasStartedRenderPass() const
return hasChildlessWritingNode() && mCurrentWritingNode->getInsideRenderPassCommands()->valid(); return hasChildlessWritingNode() && mCurrentWritingNode->getInsideRenderPassCommands()->valid();
} }
ANGLE_INLINE void CommandGraphResource::onGraphAccess(Serial serial, CommandGraph *commandGraph) ANGLE_INLINE void CommandGraphResource::onGraphAccess(CommandGraph *commandGraph)
{ {
// Store reference to usage in graph. // Clear dependencies if this is a new access. The minimum counter value is 1.
commandGraph->onResourceUse(mUse); if (mUse.getCounter() == 1)
if (serial > mUse.getSerial())
{ {
mCurrentWritingNode = nullptr; mCurrentWritingNode = nullptr;
mCurrentReadingNodes.clear(); mCurrentReadingNodes.clear();
mUse.updateSerial(serial);
} }
// Store reference to usage in graph.
commandGraph->onResourceUse(mUse);
} }
ANGLE_INLINE bool CommandGraphResource::appendToStartedRenderPass(Serial serial, ANGLE_INLINE bool CommandGraphResource::appendToStartedRenderPass(CommandGraph *graph,
CommandGraph *graph,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
CommandBuffer **commandBufferOut) CommandBuffer **commandBufferOut)
{ {
onGraphAccess(serial, graph); onGraphAccess(graph);
if (hasStartedRenderPass()) if (hasStartedRenderPass())
{ {
if (mCurrentWritingNode->getRenderPassRenderArea().encloses(renderArea)) if (mCurrentWritingNode->getRenderPassRenderArea().encloses(renderArea))
......
...@@ -496,8 +496,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -496,8 +496,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits; mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this); gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this);
if (!mDrawFramebuffer->appendToStartedRenderPass(mCurrentQueueSerial, &mCommandGraph, if (!mDrawFramebuffer->appendToStartedRenderPass(&mCommandGraph, scissoredRenderArea,
scissoredRenderArea,
&mRenderPassCommandBuffer)) &mRenderPassCommandBuffer))
{ {
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, scissoredRenderArea, ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, scissoredRenderArea,
...@@ -2988,7 +2987,7 @@ void ContextVk::waitForSwapchainImageIfNecessary() ...@@ -2988,7 +2987,7 @@ void ContextVk::waitForSwapchainImageIfNecessary()
if (waitSemaphore.valid()) if (waitSemaphore.valid())
{ {
addWaitSemaphore(waitSemaphore.getHandle()); addWaitSemaphore(waitSemaphore.getHandle());
releaseObject(getCurrentQueueSerial(), &waitSemaphore); addGarbage(&waitSemaphore);
} }
} }
} }
......
...@@ -269,16 +269,9 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -269,16 +269,9 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
bool isSerialInUse(Serial serial) const; bool isSerialInUse(Serial serial) const;
template <typename T> template <typename T>
void releaseObject(Serial resourceSerial, T *object) void addGarbage(T *object)
{ {
if (!isSerialInUse(resourceSerial)) object->dumpResources(mCurrentQueueSerial, &mGarbage);
{
object->destroy(getDevice());
}
else
{
object->dumpResources(resourceSerial, &mGarbage);
}
} }
// Check to see which batches have finished completion (forward progress for // Check to see which batches have finished completion (forward progress for
......
...@@ -196,7 +196,7 @@ angle::Result FramebufferVk::invalidate(const gl::Context *context, ...@@ -196,7 +196,7 @@ angle::Result FramebufferVk::invalidate(const gl::Context *context,
const GLenum *attachments) const GLenum *attachments)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
mFramebuffer.onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); mFramebuffer.onGraphAccess(contextVk->getCommandGraph());
if (mFramebuffer.valid() && mFramebuffer.hasStartedRenderPass()) if (mFramebuffer.valid() && mFramebuffer.hasStartedRenderPass())
{ {
...@@ -212,7 +212,7 @@ angle::Result FramebufferVk::invalidateSub(const gl::Context *context, ...@@ -212,7 +212,7 @@ angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
const gl::Rectangle &area) const gl::Rectangle &area)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
mFramebuffer.onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); mFramebuffer.onGraphAccess(contextVk->getCommandGraph());
// RenderPass' storeOp cannot be made conditional to a specific region, so we only apply this // RenderPass' storeOp cannot be made conditional to a specific region, so we only apply this
// hint if the requested area encompasses the render area. // hint if the requested area encompasses the render area.
...@@ -263,7 +263,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context, ...@@ -263,7 +263,7 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
mFramebuffer.onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); mFramebuffer.onGraphAccess(contextVk->getCommandGraph());
// This function assumes that only enabled attachments are asked to be cleared. // This function assumes that only enabled attachments are asked to be cleared.
ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers); ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
...@@ -899,8 +899,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -899,8 +899,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
vk::ImageView depthViewObject = depthView.release(); vk::ImageView depthViewObject = depthView.release();
vk::ImageView stencilViewObject = stencilView.release(); vk::ImageView stencilViewObject = stencilView.release();
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &depthViewObject); contextVk->addGarbage(&depthViewObject);
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &stencilViewObject); contextVk->addGarbage(&stencilViewObject);
} }
} }
...@@ -1485,8 +1485,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -1485,8 +1485,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
contextVk, renderer->getMemoryProperties(), gl::Extents(area.width, area.height, 1), contextVk, renderer->getMemoryProperties(), gl::Extents(area.width, area.height, 1),
srcImage->getFormat(), srcImage->getFormat(),
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 1)); VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 1));
resolvedImage.get().onGraphAccess(contextVk->getCurrentQueueSerial(), resolvedImage.get().onGraphAccess(contextVk->getCommandGraph());
contextVk->getCommandGraph());
// Note: resolve only works on color images (not depth/stencil). // Note: resolve only works on color images (not depth/stencil).
// //
...@@ -1605,7 +1604,7 @@ void FramebufferVk::onScissorChange(ContextVk *contextVk) ...@@ -1605,7 +1604,7 @@ void FramebufferVk::onScissorChange(ContextVk *contextVk)
// is too small, we need to start a new one. The latter can happen if a scissored clear starts // is too small, we need to start a new one. The latter can happen if a scissored clear starts
// a render pass, the scissor is disabled and a draw call is issued to affect the whole // a render pass, the scissor is disabled and a draw call is issued to affect the whole
// framebuffer. // framebuffer.
mFramebuffer.onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); mFramebuffer.onGraphAccess(contextVk->getCommandGraph());
if (mFramebuffer.hasStartedRenderPass() && if (mFramebuffer.hasStartedRenderPass() &&
!mFramebuffer.getRenderPassRenderArea().encloses(scissoredRenderArea)) !mFramebuffer.getRenderPassRenderArea().encloses(scissoredRenderArea))
{ {
......
...@@ -112,13 +112,11 @@ class FramebufferVk : public FramebufferImpl ...@@ -112,13 +112,11 @@ class FramebufferVk : public FramebufferImpl
RenderTargetVk *getColorReadRenderTarget() const; RenderTargetVk *getColorReadRenderTarget() const;
// This will clear the current write operation if it is complete. // This will clear the current write operation if it is complete.
bool appendToStartedRenderPass(Serial currentQueueSerial, bool appendToStartedRenderPass(vk::CommandGraph *graph,
vk::CommandGraph *graph,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
return mFramebuffer.appendToStartedRenderPass(currentQueueSerial, graph, renderArea, return mFramebuffer.appendToStartedRenderPass(graph, renderArea, commandBufferOut);
commandBufferOut);
} }
vk::FramebufferHelper *getFramebuffer() { return &mFramebuffer; } vk::FramebufferHelper *getFramebuffer() { return &mFramebuffer; }
......
...@@ -151,9 +151,8 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk) ...@@ -151,9 +151,8 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk)
RendererVk *rendererVk = contextVk->getRenderer(); RendererVk *rendererVk = contextVk->getRenderer();
// Release old culledWidgets image // Release old culledWidgets image
Serial currentSerial = contextVk->getCurrentQueueSerial(); contextVk->addGarbage(&mCulledWidgets);
contextVk->releaseObject(currentSerial, &mCulledWidgets); contextVk->addGarbage(&mCulledWidgetsView);
contextVk->releaseObject(currentSerial, &mCulledWidgetsView);
// Create a buffer to contain coordinates of enabled text and graph widgets. This buffer will // Create a buffer to contain coordinates of enabled text and graph widgets. This buffer will
// be used to perform tiled culling and can be discarded immediately after. // be used to perform tiled culling and can be discarded immediately after.
......
...@@ -1233,8 +1233,7 @@ void ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk) ...@@ -1233,8 +1233,7 @@ void ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
} }
else else
{ {
mEmptyBuffer.onGraphAccess(contextVk->getCurrentQueueSerial(), mEmptyBuffer.onGraphAccess(contextVk->getCommandGraph());
contextVk->getCommandGraph());
bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle(); bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
} }
...@@ -1399,7 +1398,7 @@ void ProgramVk::updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk, ...@@ -1399,7 +1398,7 @@ void ProgramVk::updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
} }
// Bind the empty buffer to every array slot that's unused. // Bind the empty buffer to every array slot that's unused.
mEmptyBuffer.onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); mEmptyBuffer.onGraphAccess(contextVk->getCommandGraph());
for (size_t binding : ~writtenBindings) for (size_t binding : ~writtenBindings)
{ {
VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding]; VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
......
...@@ -233,8 +233,8 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk) ...@@ -233,8 +233,8 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk)
mImage = nullptr; mImage = nullptr;
} }
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mImageView); contextVk->addGarbage(&mImageView);
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mCubeImageFetchView); contextVk->addGarbage(&mCubeImageFetchView);
} }
} // namespace rx } // namespace rx
...@@ -23,7 +23,7 @@ SamplerVk::~SamplerVk() = default; ...@@ -23,7 +23,7 @@ SamplerVk::~SamplerVk() = default;
void SamplerVk::onDestroy(const gl::Context *context) void SamplerVk::onDestroy(const gl::Context *context)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mSampler); contextVk->addGarbage(&mSampler);
} }
const vk::Sampler &SamplerVk::getSampler() const const vk::Sampler &SamplerVk::getSampler() const
...@@ -43,7 +43,7 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty) ...@@ -43,7 +43,7 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mSampler); contextVk->addGarbage(&mSampler);
} }
const gl::Extensions &extensions = renderer->getNativeExtensions(); const gl::Extensions &extensions = renderer->getNativeExtensions();
......
...@@ -22,7 +22,7 @@ SemaphoreVk::~SemaphoreVk() = default; ...@@ -22,7 +22,7 @@ SemaphoreVk::~SemaphoreVk() = default;
void SemaphoreVk::onDestroy(const gl::Context *context) void SemaphoreVk::onDestroy(const gl::Context *context)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mSemaphore); contextVk->addGarbage(&mSemaphore);
} }
angle::Result SemaphoreVk::importFd(gl::Context *context, gl::HandleType handleType, GLint fd) angle::Result SemaphoreVk::importFd(gl::Context *context, gl::HandleType handleType, GLint fd)
......
...@@ -896,36 +896,32 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk) ...@@ -896,36 +896,32 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk)
{ {
if (mDepthStencilImage.valid()) if (mDepthStencilImage.valid())
{ {
Serial depthStencilSerial = mDepthStencilImage.getStoredQueueSerial();
mDepthStencilImage.releaseImage(contextVk); mDepthStencilImage.releaseImage(contextVk);
mDepthStencilImage.releaseStagingBuffer(contextVk); mDepthStencilImage.releaseStagingBuffer(contextVk);
if (mDepthStencilImageView.valid()) if (mDepthStencilImageView.valid())
{ {
contextVk->releaseObject(depthStencilSerial, &mDepthStencilImageView); contextVk->addGarbage(&mDepthStencilImageView);
} }
} }
if (mColorImageMS.valid()) if (mColorImageMS.valid())
{ {
Serial serial = mColorImageMS.getStoredQueueSerial();
mColorImageMS.releaseImage(contextVk); mColorImageMS.releaseImage(contextVk);
mColorImageMS.releaseStagingBuffer(contextVk); mColorImageMS.releaseStagingBuffer(contextVk);
contextVk->releaseObject(serial, &mColorImageViewMS); contextVk->addGarbage(&mColorImageViewMS);
contextVk->releaseObject(serial, &mFramebufferMS); contextVk->addGarbage(&mFramebufferMS);
} }
for (SwapchainImage &swapchainImage : mSwapchainImages) for (SwapchainImage &swapchainImage : mSwapchainImages)
{ {
Serial imageSerial = swapchainImage.image.getStoredQueueSerial();
// We don't own the swapchain image handles, so we just remove our reference to it. // We don't own the swapchain image handles, so we just remove our reference to it.
swapchainImage.image.resetImageWeakReference(); swapchainImage.image.resetImageWeakReference();
swapchainImage.image.destroy(contextVk->getDevice()); swapchainImage.image.destroy(contextVk->getDevice());
contextVk->releaseObject(imageSerial, &swapchainImage.imageView); contextVk->addGarbage(&swapchainImage.imageView);
contextVk->releaseObject(imageSerial, &swapchainImage.framebuffer); contextVk->addGarbage(&swapchainImage.framebuffer);
// present history must have already been taken care of. // present history must have already been taken care of.
for (ImagePresentHistory &presentHistory : swapchainImage.presentHistory) for (ImagePresentHistory &presentHistory : swapchainImage.presentHistory)
...@@ -1230,17 +1226,6 @@ VkResult WindowSurfaceVk::nextSwapchainImage(vk::Context *context) ...@@ -1230,17 +1226,6 @@ VkResult WindowSurfaceVk::nextSwapchainImage(vk::Context *context)
SwapchainImage &image = mSwapchainImages[mCurrentSwapchainImageIndex]; SwapchainImage &image = mSwapchainImages[mCurrentSwapchainImageIndex];
// This swap chain image is new, reset any dependency information it has.
//
// When the Vulkan backend is multithreading, different contexts can have very different current
// serials. If a surface is rendered to by multiple contexts in different frames, the last
// context to write a particular swap chain image has no bearing on the current context writing
// to that image.
//
// Clear the image's queue serial because it's possible that it appears to be in the future to
// the next context that writes to the image.
image.image.resetQueueSerial();
// Update RenderTarget pointers to this swapchain image if not multisampling. Note: a possible // Update RenderTarget pointers to this swapchain image if not multisampling. Note: a possible
// optimization is to defer the |vkAcquireNextImageKHR| call itself to |present()| if // optimization is to defer the |vkAcquireNextImageKHR| call itself to |present()| if
// multisampling, as the swapchain image is essentially unused until then. // multisampling, as the swapchain image is essentially unused until then.
......
...@@ -25,7 +25,7 @@ void FenceSyncVk::onDestroy(ContextVk *contextVk) ...@@ -25,7 +25,7 @@ void FenceSyncVk::onDestroy(ContextVk *contextVk)
{ {
if (mEvent.valid()) if (mEvent.valid())
{ {
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mEvent); contextVk->addGarbage(&mEvent);
} }
for (vk::Shared<vk::Fence> &fence : mFences) for (vk::Shared<vk::Fence> &fence : mFences)
......
...@@ -83,13 +83,13 @@ bool HasBothDepthAndStencilAspects(VkImageAspectFlags aspectFlags) ...@@ -83,13 +83,13 @@ bool HasBothDepthAndStencilAspects(VkImageAspectFlags aspectFlags)
TextureVk::TextureVkViews::TextureVkViews() {} TextureVk::TextureVkViews::TextureVkViews() {}
TextureVk::TextureVkViews::~TextureVkViews() {} TextureVk::TextureVkViews::~TextureVkViews() {}
void TextureVk::TextureVkViews::release(ContextVk *contextVk, Serial currentSerial) void TextureVk::TextureVkViews::release(ContextVk *contextVk)
{ {
contextVk->releaseObject(currentSerial, &mDrawBaseLevelImageView); contextVk->addGarbage(&mDrawBaseLevelImageView);
contextVk->releaseObject(currentSerial, &mReadBaseLevelImageView); contextVk->addGarbage(&mReadBaseLevelImageView);
contextVk->releaseObject(currentSerial, &mReadMipmapImageView); contextVk->addGarbage(&mReadMipmapImageView);
contextVk->releaseObject(currentSerial, &mFetchBaseLevelImageView); contextVk->addGarbage(&mFetchBaseLevelImageView);
contextVk->releaseObject(currentSerial, &mFetchMipmapImageView); contextVk->addGarbage(&mFetchMipmapImageView);
} }
angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk, angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
...@@ -159,7 +159,7 @@ void TextureVk::onDestroy(const gl::Context *context) ...@@ -159,7 +159,7 @@ void TextureVk::onDestroy(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
releaseAndDeleteImage(contextVk); releaseAndDeleteImage(contextVk);
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mSampler); contextVk->addGarbage(&mSampler);
} }
angle::Result TextureVk::setImage(const gl::Context *context, angle::Result TextureVk::setImage(const gl::Context *context,
...@@ -660,9 +660,8 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -660,9 +660,8 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
vk::ImageHelper *srcImage, vk::ImageHelper *srcImage,
const vk::ImageView *srcView) const vk::ImageView *srcView)
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
UtilsVk &utilsVk = contextVk->getUtils(); UtilsVk &utilsVk = contextVk->getUtils();
Serial currentQueueSerial = contextVk->getCurrentQueueSerial();
UtilsVk::CopyImageParameters params; UtilsVk::CopyImageParameters params;
params.srcOffset[0] = sourceArea.x; params.srcOffset[0] = sourceArea.x;
...@@ -731,7 +730,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -731,7 +730,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
// Queue the resource for cleanup as soon as the copy above is finished. There's no // Queue the resource for cleanup as soon as the copy above is finished. There's no
// need to keep it around. // need to keep it around.
contextVk->releaseObject(currentQueueSerial, &stagingView); contextVk->addGarbage(&stagingView);
} }
// Stage the copy for when the image storage is actually created. // Stage the copy for when the image storage is actually created.
...@@ -1294,7 +1293,7 @@ angle::Result TextureVk::syncState(const gl::Context *context, ...@@ -1294,7 +1293,7 @@ angle::Result TextureVk::syncState(const gl::Context *context,
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
if (mSampler.valid()) if (mSampler.valid())
{ {
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mSampler); contextVk->addGarbage(&mSampler);
} }
if (dirtyBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) || if (dirtyBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) ||
...@@ -1695,35 +1694,32 @@ void TextureVk::releaseImage(ContextVk *contextVk) ...@@ -1695,35 +1694,32 @@ void TextureVk::releaseImage(ContextVk *contextVk)
void TextureVk::releaseImageViews(ContextVk *contextVk) void TextureVk::releaseImageViews(ContextVk *contextVk)
{ {
Serial currentSerial = contextVk->getCurrentQueueSerial(); mDefaultViews.release(contextVk);
mStencilViews.release(contextVk);
mDefaultViews.release(contextVk, currentSerial);
mStencilViews.release(contextVk, currentSerial);
for (vk::ImageViewVector &layerViews : mLayerLevelDrawImageViews) for (vk::ImageViewVector &layerViews : mLayerLevelDrawImageViews)
{ {
for (vk::ImageView &imageView : layerViews) for (vk::ImageView &imageView : layerViews)
{ {
contextVk->releaseObject(currentSerial, &imageView); contextVk->addGarbage(&imageView);
} }
} }
mLayerLevelDrawImageViews.clear(); mLayerLevelDrawImageViews.clear();
for (vk::ImageView &imageView : mLayerFetchImageView) for (vk::ImageView &imageView : mLayerFetchImageView)
{ {
contextVk->releaseObject(currentSerial, &imageView); contextVk->addGarbage(&imageView);
} }
mLayerFetchImageView.clear(); mLayerFetchImageView.clear();
for (vk::ImageView &imageView : mLevelStorageImageViews) for (vk::ImageView &imageView : mLevelStorageImageViews)
{ {
contextVk->releaseObject(currentSerial, &imageView); contextVk->addGarbage(&imageView);
} }
mLevelStorageImageViews.clear(); mLevelStorageImageViews.clear();
for (vk::ImageViewVector &layerViews : mLayerLevelStorageImageViews) for (vk::ImageViewVector &layerViews : mLayerLevelStorageImageViews)
{ {
for (vk::ImageView &imageView : layerViews) for (vk::ImageView &imageView : layerViews)
{ {
contextVk->releaseObject(currentSerial, &imageView); contextVk->addGarbage(&imageView);
} }
} }
mLayerLevelStorageImageViews.clear(); mLayerLevelStorageImageViews.clear();
......
...@@ -184,7 +184,8 @@ class TextureVk : public TextureImpl ...@@ -184,7 +184,8 @@ class TextureVk : public TextureImpl
TextureVkViews(); TextureVkViews();
~TextureVkViews(); ~TextureVkViews();
void release(ContextVk *contextVk, Serial currentSerial); void release(ContextVk *contextVk);
vk::ImageView mDrawBaseLevelImageView; vk::ImageView mDrawBaseLevelImageView;
vk::ImageView mReadBaseLevelImageView; vk::ImageView mReadBaseLevelImageView;
vk::ImageView mReadMipmapImageView; vk::ImageView mReadMipmapImageView;
......
...@@ -237,7 +237,7 @@ void TransformFeedbackVk::onBeginOrEnd(const gl::Context *context) ...@@ -237,7 +237,7 @@ void TransformFeedbackVk::onBeginOrEnd(const gl::Context *context)
FramebufferVk *framebufferVk = vk::GetImpl(context->getState().getDrawFramebuffer()); FramebufferVk *framebufferVk = vk::GetImpl(context->getState().getDrawFramebuffer());
vk::FramebufferHelper *framebuffer = framebufferVk->getFramebuffer(); vk::FramebufferHelper *framebuffer = framebufferVk->getFramebuffer();
framebuffer->onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); framebuffer->onGraphAccess(contextVk->getCommandGraph());
if (framebuffer->hasStartedRenderPass()) if (framebuffer->hasStartedRenderPass())
{ {
framebuffer->finishCurrentCommands(contextVk); framebuffer->finishCurrentCommands(contextVk);
......
...@@ -941,7 +941,7 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, ...@@ -941,7 +941,7 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc, ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, clearValues, commandBufferOut)); renderPassAttachmentOps, clearValues, commandBufferOut));
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &framebuffer); contextVk->addGarbage(&framebuffer);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -955,8 +955,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -955,8 +955,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea = params.clearArea; const gl::Rectangle &scissoredRenderArea = params.clearArea;
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
if (!framebuffer->appendToStartedRenderPass(contextVk->getCurrentQueueSerial(), if (!framebuffer->appendToStartedRenderPass(contextVk->getCommandGraph(), scissoredRenderArea,
contextVk->getCommandGraph(), scissoredRenderArea,
&commandBuffer)) &commandBuffer))
{ {
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, scissoredRenderArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, scissoredRenderArea, &commandBuffer));
...@@ -1185,8 +1184,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1185,8 +1184,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
} }
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
if (!framebuffer->appendToStartedRenderPass(contextVk->getCurrentQueueSerial(), if (!framebuffer->appendToStartedRenderPass(contextVk->getCommandGraph(), params.blitArea,
contextVk->getCommandGraph(), params.blitArea,
&commandBuffer)) &commandBuffer))
{ {
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
...@@ -1297,8 +1295,7 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, ...@@ -1297,8 +1295,7 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
ANGLE_TRY( ANGLE_TRY(
blitBuffer.get().init(contextVk, blitBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); blitBuffer.get().init(contextVk, blitBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
blitBuffer.get().onGraphAccess(contextVk->getCurrentQueueSerial(), blitBuffer.get().onGraphAccess(contextVk->getCommandGraph());
contextVk->getCommandGraph());
BlitResolveStencilNoExportShaderParams shaderParams; BlitResolveStencilNoExportShaderParams shaderParams;
if (isResolve) if (isResolve)
......
...@@ -1690,7 +1690,7 @@ void GraphicsPipelineCache::release(ContextVk *context) ...@@ -1690,7 +1690,7 @@ void GraphicsPipelineCache::release(ContextVk *context)
for (auto &item : mPayload) for (auto &item : mPayload)
{ {
vk::PipelineHelper &pipeline = item.second; vk::PipelineHelper &pipeline = item.second;
context->releaseObject(pipeline.getSerial(), &pipeline.getPipeline()); context->addGarbage(&pipeline.getPipeline());
} }
mPayload.clear(); mPayload.clear();
......
...@@ -354,8 +354,7 @@ angle::Result DynamicBuffer::allocate(ContextVk *contextVk, ...@@ -354,8 +354,7 @@ angle::Result DynamicBuffer::allocate(ContextVk *contextVk,
{ {
ANGLE_TRY(flush(contextVk)); ANGLE_TRY(flush(contextVk));
mBuffer->unmap(contextVk->getDevice()); mBuffer->unmap(contextVk->getDevice());
mBuffer->onGraphAccess(contextVk->getCurrentQueueSerial(), mBuffer->onGraphAccess(contextVk->getCommandGraph());
contextVk->getCommandGraph());
mInFlightBuffers.push_back(mBuffer); mInFlightBuffers.push_back(mBuffer);
mBuffer = nullptr; mBuffer = nullptr;
...@@ -495,7 +494,7 @@ void DynamicBuffer::release(ContextVk *contextVk) ...@@ -495,7 +494,7 @@ void DynamicBuffer::release(ContextVk *contextVk)
// The buffers may not have been recording commands, but they could be used to store data so // The buffers may not have been recording commands, but they could be used to store data so
// they should live until at most this frame. For example a vertex buffer filled entirely // they should live until at most this frame. For example a vertex buffer filled entirely
// by the CPU currently never gets a chance to have its serial set. // by the CPU currently never gets a chance to have its serial set.
mBuffer->onGraphAccess(contextVk->getCurrentQueueSerial(), contextVk->getCommandGraph()); mBuffer->onGraphAccess(contextVk->getCommandGraph());
mBuffer->release(contextVk); mBuffer->release(contextVk);
delete mBuffer; delete mBuffer;
mBuffer = nullptr; mBuffer = nullptr;
...@@ -645,7 +644,7 @@ void DescriptorPoolHelper::destroy(VkDevice device) ...@@ -645,7 +644,7 @@ void DescriptorPoolHelper::destroy(VkDevice device)
void DescriptorPoolHelper::release(ContextVk *contextVk) void DescriptorPoolHelper::release(ContextVk *contextVk)
{ {
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mDescriptorPool); contextVk->addGarbage(&mDescriptorPool);
} }
angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk, angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk,
...@@ -1306,9 +1305,9 @@ void BufferHelper::release(ContextVk *contextVk) ...@@ -1306,9 +1305,9 @@ void BufferHelper::release(ContextVk *contextVk)
mSize = 0; mSize = 0;
mViewFormat = nullptr; mViewFormat = nullptr;
contextVk->releaseObject(getStoredQueueSerial(), &mBuffer); contextVk->addGarbage(&mBuffer);
contextVk->releaseObject(getStoredQueueSerial(), &mBufferView); contextVk->addGarbage(&mBufferView);
contextVk->releaseObject(getStoredQueueSerial(), &mDeviceMemory); contextVk->addGarbage(&mDeviceMemory);
} }
void BufferHelper::release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue) void BufferHelper::release(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
...@@ -1568,8 +1567,8 @@ angle::Result ImageHelper::initExternal(Context *context, ...@@ -1568,8 +1567,8 @@ angle::Result ImageHelper::initExternal(Context *context,
void ImageHelper::releaseImage(ContextVk *contextVk) void ImageHelper::releaseImage(ContextVk *contextVk)
{ {
contextVk->releaseObject(getStoredQueueSerial(), &mImage); contextVk->addGarbage(&mImage);
contextVk->releaseObject(getStoredQueueSerial(), &mDeviceMemory); contextVk->addGarbage(&mDeviceMemory);
} }
void ImageHelper::releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue) void ImageHelper::releaseImage(DisplayVk *display, std::vector<GarbageObjectBase> *garbageQueue)
...@@ -2730,7 +2729,7 @@ angle::Result FramebufferHelper::init(ContextVk *contextVk, ...@@ -2730,7 +2729,7 @@ angle::Result FramebufferHelper::init(ContextVk *contextVk,
void FramebufferHelper::release(ContextVk *contextVk) void FramebufferHelper::release(ContextVk *contextVk)
{ {
contextVk->releaseObject(getStoredQueueSerial(), &mFramebuffer); contextVk->addGarbage(&mFramebuffer);
} }
// FramebufferHelper implementation. // FramebufferHelper implementation.
...@@ -2762,7 +2761,7 @@ void ShaderProgramHelper::destroy(VkDevice device) ...@@ -2762,7 +2761,7 @@ void ShaderProgramHelper::destroy(VkDevice device)
void ShaderProgramHelper::release(ContextVk *contextVk) void ShaderProgramHelper::release(ContextVk *contextVk)
{ {
mGraphicsPipelines.release(contextVk); mGraphicsPipelines.release(contextVk);
contextVk->releaseObject(mComputePipeline.getSerial(), &mComputePipeline.get()); contextVk->addGarbage(&mComputePipeline.get());
for (BindingPointer<ShaderAndSerial> &shader : mShaders) for (BindingPointer<ShaderAndSerial> &shader : mShaders)
{ {
shader.reset(); shader.reset();
......
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