Commit e4c5a23b by Jamie Madill Committed by Commit Bot

Vulkan: Always use LOAD for RenderPass attachments.

The RenderPass load/store ops allow us to specify how we want to use the data from the attachments. Previously we had the load op set to CLEAR always, which would prevent us from doing multiple kinds of operation. Using LOAD should conversatively work in any situation as long as we can ensure each Image is cleared before we use it. To this effect this patch also inserts a preliminary clear into each Texture or Renderbuffer Image's initialization. We already had this for Surfaces. In the future we'll improve this by inserting proper load/store ops, but this unblocks a lot more functionality in the interim. Bug: angleproject:2361 Change-Id: I7610eaa39d81b23dd74b4a24b7f28a66a6dfffc6 Reviewed-on: https://chromium-review.googlesource.com/948782 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarLuc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 37812d45
...@@ -191,18 +191,18 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -191,18 +191,18 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
Serial queueSerial = mRenderer->getCurrentQueueSerial(); Serial queueSerial = mRenderer->getCurrentQueueSerial();
uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation(); uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
vk::CommandGraphNode *renderNode = nullptr; vk::CommandGraphNode *graphNode = nullptr;
ANGLE_TRY(vkFBO->getRenderNode(context, &renderNode)); ANGLE_TRY(vkFBO->getCommandGraphNodeForDraw(context, &graphNode));
if (!renderNode->getInsideRenderPassCommands()->valid()) if (!graphNode->getInsideRenderPassCommands()->valid())
{ {
mVertexArrayDirty = true; mVertexArrayDirty = true;
mTexturesDirty = true; mTexturesDirty = true;
ANGLE_TRY(renderNode->beginInsideRenderPassRecording(mRenderer, commandBuffer)); ANGLE_TRY(graphNode->beginInsideRenderPassRecording(mRenderer, commandBuffer));
} }
else else
{ {
*commandBuffer = renderNode->getInsideRenderPassCommands(); *commandBuffer = graphNode->getInsideRenderPassCommands();
} }
// Ensure any writes to the VAO buffers are flushed before we read from them. // Ensure any writes to the VAO buffers are flushed before we read from them.
...@@ -210,7 +210,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -210,7 +210,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
{ {
mVertexArrayDirty = false; mVertexArrayDirty = false;
vkVAO->updateDrawDependencies(renderNode, programGL->getActiveAttribLocationsMask(), vkVAO->updateDrawDependencies(graphNode, programGL->getActiveAttribLocationsMask(),
elementArrayBufferOverride, queueSerial, drawType); elementArrayBufferOverride, queueSerial, drawType);
} }
...@@ -234,7 +234,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -234,7 +234,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
ASSERT(texture); ASSERT(texture);
TextureVk *textureVk = vk::GetImpl(texture); TextureVk *textureVk = vk::GetImpl(texture);
textureVk->onReadResource(renderNode, mRenderer->getCurrentQueueSerial()); textureVk->onReadResource(graphNode, mRenderer->getCurrentQueueSerial());
} }
} }
......
...@@ -467,7 +467,8 @@ gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const ...@@ -467,7 +467,8 @@ gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
return gl::InternalError() << "getSamplePosition is unimplemented."; return gl::InternalError() << "getSamplePosition is unimplemented.";
} }
gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGraphNode **nodeOut) gl::Error FramebufferVk::getCommandGraphNodeForDraw(const gl::Context *context,
vk::CommandGraphNode **nodeOut)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
...@@ -487,6 +488,10 @@ gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGr ...@@ -487,6 +488,10 @@ gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGr
std::vector<VkClearValue> attachmentClearValues; std::vector<VkClearValue> attachmentClearValues;
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(node->beginOutsideRenderPassRecording(renderer->getDevice(),
renderer->getCommandPool(), &commandBuffer));
// Initialize RenderPass info. // Initialize RenderPass info.
// TODO(jmadill): Could cache this info, would require dependent state change messaging. // TODO(jmadill): Could cache this info, would require dependent state change messaging.
const auto &colorAttachments = mState.getColorAttachments(); const auto &colorAttachments = mState.getColorAttachments();
...@@ -498,8 +503,11 @@ gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGr ...@@ -498,8 +503,11 @@ gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGr
RenderTargetVk *renderTarget = nullptr; RenderTargetVk *renderTarget = nullptr;
ANGLE_SWALLOW_ERR(colorAttachment.getRenderTarget(context, &renderTarget)); ANGLE_SWALLOW_ERR(colorAttachment.getRenderTarget(context, &renderTarget));
// TODO(jmadill): May need layout transition. // TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
renderTarget->image->updateLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); renderTarget->image->changeLayoutWithStages(
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
commandBuffer);
node->appendColorRenderTarget(currentSerial, renderTarget); node->appendColorRenderTarget(currentSerial, renderTarget);
attachmentClearValues.emplace_back(contextVk->getClearColorValue()); attachmentClearValues.emplace_back(contextVk->getClearColorValue());
} }
...@@ -511,8 +519,15 @@ gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGr ...@@ -511,8 +519,15 @@ gl::Error FramebufferVk::getRenderNode(const gl::Context *context, vk::CommandGr
RenderTargetVk *renderTarget = nullptr; RenderTargetVk *renderTarget = nullptr;
ANGLE_SWALLOW_ERR(depthStencilAttachment->getRenderTarget(context, &renderTarget)); ANGLE_SWALLOW_ERR(depthStencilAttachment->getRenderTarget(context, &renderTarget));
// TODO(jmadill): May need layout transition. // TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
renderTarget->image->updateLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); const angle::Format &format = renderTarget->format->textureFormat();
VkImageAspectFlags aspectFlags = (format.depthBits > 0 ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
(format.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
renderTarget->image->changeLayoutWithStages(
aspectFlags, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
commandBuffer);
node->appendDepthStencilRenderTarget(currentSerial, renderTarget); node->appendDepthStencilRenderTarget(currentSerial, renderTarget);
attachmentClearValues.emplace_back(contextVk->getClearDepthStencilValue()); attachmentClearValues.emplace_back(contextVk->getClearDepthStencilValue());
} }
......
...@@ -85,7 +85,8 @@ class FramebufferVk : public FramebufferImpl, public ResourceVk ...@@ -85,7 +85,8 @@ class FramebufferVk : public FramebufferImpl, public ResourceVk
gl::Error getSamplePosition(size_t index, GLfloat *xy) const override; gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
const vk::RenderPassDesc &getRenderPassDesc(const gl::Context *context); const vk::RenderPassDesc &getRenderPassDesc(const gl::Context *context);
gl::Error getRenderNode(const gl::Context *context, vk::CommandGraphNode **nodeOut); gl::Error getCommandGraphNodeForDraw(const gl::Context *context,
vk::CommandGraphNode **nodeOut);
private: private:
FramebufferVk(const gl::FramebufferState &state); FramebufferVk(const gl::FramebufferState &state);
......
...@@ -127,6 +127,15 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context, ...@@ -127,6 +127,15 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context,
viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.layerCount = 1;
ANGLE_TRY(mImageView.init(device, viewInfo)); ANGLE_TRY(mImageView.init(device, viewInfo));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
VkClearColorValue black = {{0}};
mImage.changeLayoutWithStages(
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
commandBuffer->clearSingleColorImage(mImage, black);
} }
return gl::NoError(); return gl::NoError();
......
...@@ -139,6 +139,15 @@ gl::Error TextureVk::setImage(const gl::Context *context, ...@@ -139,6 +139,15 @@ gl::Error TextureVk::setImage(const gl::Context *context,
viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.layerCount = 1;
ANGLE_TRY(mImageView.init(device, viewInfo)); ANGLE_TRY(mImageView.init(device, viewInfo));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
VkClearColorValue black = {{0}};
mImage.changeLayoutWithStages(
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
commandBuffer->clearSingleColorImage(mImage, black);
} }
if (!mSampler.valid()) if (!mSampler.valid())
......
...@@ -698,15 +698,17 @@ PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](size_t index) ...@@ -698,15 +698,17 @@ PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](size_t index)
return mOps[index]; return mOps[index];
} }
void AttachmentOpsArray::initDummyOp(size_t index, VkImageLayout finalLayout) void AttachmentOpsArray::initDummyOp(size_t index,
VkImageLayout initialLayout,
VkImageLayout finalLayout)
{ {
PackedAttachmentOpsDesc &ops = mOps[index]; PackedAttachmentOpsDesc &ops = mOps[index];
ops.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; ops.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
ops.storeOp = VK_ATTACHMENT_STORE_OP_STORE; ops.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
ops.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; ops.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
ops.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; ops.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
ops.initialLayout = static_cast<uint16_t>(VK_IMAGE_LAYOUT_UNDEFINED); ops.initialLayout = static_cast<uint16_t>(initialLayout);
ops.finalLayout = static_cast<uint16_t>(finalLayout); ops.finalLayout = static_cast<uint16_t>(finalLayout);
} }
...@@ -765,12 +767,14 @@ vk::Error RenderPassCache::getCompatibleRenderPass(VkDevice device, ...@@ -765,12 +767,14 @@ vk::Error RenderPassCache::getCompatibleRenderPass(VkDevice device,
vk::AttachmentOpsArray ops; vk::AttachmentOpsArray ops;
for (uint32_t colorIndex = 0; colorIndex < desc.colorAttachmentCount(); ++colorIndex) for (uint32_t colorIndex = 0; colorIndex < desc.colorAttachmentCount(); ++colorIndex)
{ {
ops.initDummyOp(colorIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); ops.initDummyOp(colorIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
} }
if (desc.depthStencilAttachmentCount() > 0) if (desc.depthStencilAttachmentCount() > 0)
{ {
ops.initDummyOp(desc.colorAttachmentCount(), ops.initDummyOp(desc.colorAttachmentCount(),
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
} }
......
...@@ -103,7 +103,7 @@ class AttachmentOpsArray final ...@@ -103,7 +103,7 @@ class AttachmentOpsArray final
PackedAttachmentOpsDesc &operator[](size_t index); PackedAttachmentOpsDesc &operator[](size_t index);
// Initializes an attachment op with whatever values. Used for compatible RenderPass checks. // Initializes an attachment op with whatever values. Used for compatible RenderPass checks.
void initDummyOp(size_t index, VkImageLayout finalLayout); void initDummyOp(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
size_t hash() const; size_t hash() const;
......
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