Vulkan: Configure a simple RenderPass for drawing.
BUG=angleproject:1319
Change-Id: I0668527a338a2f10ca74b43f2a8bd82534e732c0
Reviewed-on: https://chromium-review.googlesource.com/370805
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index f90bba1..522ec4f 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -38,6 +38,29 @@
return &gl::GetInternalFormatInfo(implFormat);
}
+VkSampleCountFlagBits ConvertSamples(GLint sampleCount)
+{
+ switch (sampleCount)
+ {
+ case 0:
+ case 1:
+ return VK_SAMPLE_COUNT_1_BIT;
+ case 2:
+ return VK_SAMPLE_COUNT_2_BIT;
+ case 4:
+ return VK_SAMPLE_COUNT_4_BIT;
+ case 8:
+ return VK_SAMPLE_COUNT_8_BIT;
+ case 16:
+ return VK_SAMPLE_COUNT_16_BIT;
+ case 32:
+ return VK_SAMPLE_COUNT_32_BIT;
+ default:
+ UNREACHABLE();
+ return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
+ }
+}
+
} // anonymous namespace
// static
@@ -53,12 +76,19 @@
return new FramebufferVk(state, backbuffer);
}
-FramebufferVk::FramebufferVk(const gl::FramebufferState &state) : FramebufferImpl(state)
+FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
+ : FramebufferImpl(state),
+ mBackbuffer(nullptr),
+ mRenderPass(VK_NULL_HANDLE),
+ mFramebuffer(VK_NULL_HANDLE)
{
}
FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
- : FramebufferImpl(state)
+ : FramebufferImpl(state),
+ mBackbuffer(backbuffer),
+ mRenderPass(VK_NULL_HANDLE),
+ mFramebuffer(VK_NULL_HANDLE)
{
}
@@ -294,6 +324,184 @@
void FramebufferVk::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
{
// TODO(jmadill): Smarter update.
+ mRenderPass = vk::RenderPass();
+ mFramebuffer = vk::Framebuffer();
+}
+
+gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
+{
+ if (mRenderPass.valid())
+ {
+ return &mRenderPass;
+ }
+
+ // TODO(jmadill): Can we use stack-only memory?
+ std::vector<VkAttachmentDescription> attachmentDescs;
+ std::vector<VkAttachmentReference> colorAttachmentRefs;
+
+ const auto &colorAttachments = mState.getColorAttachments();
+ for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
+ {
+ const auto &colorAttachment = colorAttachments[attachmentIndex];
+ if (colorAttachment.isAttached())
+ {
+ VkAttachmentDescription colorDesc;
+ VkAttachmentReference colorRef;
+
+ RenderTargetVk *renderTarget = nullptr;
+ ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
+
+ // TODO(jmadill): We would only need this flag for duplicated attachments.
+ colorDesc.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
+ colorDesc.format = renderTarget->format->native;
+ colorDesc.samples = ConvertSamples(colorAttachment.getSamples());
+
+ // The load op controls the prior existing depth/color attachment data.
+ // TODO(jmadill): Proper load ops. Should not be hard coded to clear.
+ colorDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ colorDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ colorDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ colorDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ colorDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ colorDesc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+ colorRef.attachment = static_cast<uint32_t>(colorAttachments.size()) - 1u;
+ colorRef.layout = VK_IMAGE_LAYOUT_GENERAL;
+
+ attachmentDescs.push_back(colorDesc);
+ colorAttachmentRefs.push_back(colorRef);
+ }
+ }
+
+ const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
+ VkAttachmentReference depthStencilAttachmentRef;
+ bool useDepth = depthStencilAttachment && depthStencilAttachment->isAttached();
+
+ if (useDepth)
+ {
+ VkAttachmentDescription depthStencilDesc;
+
+ RenderTargetVk *renderTarget = nullptr;
+ ANGLE_TRY(depthStencilAttachment->getRenderTarget(&renderTarget));
+
+ depthStencilDesc.flags = 0;
+ depthStencilDesc.format = renderTarget->format->native;
+ depthStencilDesc.samples = ConvertSamples(depthStencilAttachment->getSamples());
+ depthStencilDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ depthStencilDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ depthStencilDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ depthStencilDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ depthStencilDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ depthStencilDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ depthStencilAttachmentRef.attachment = static_cast<uint32_t>(attachmentDescs.size());
+ depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ attachmentDescs.push_back(depthStencilDesc);
+ }
+
+ ASSERT(!attachmentDescs.empty());
+
+ VkSubpassDescription subpassDesc;
+
+ subpassDesc.flags = 0;
+ subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpassDesc.inputAttachmentCount = 0;
+ subpassDesc.pInputAttachments = nullptr;
+ subpassDesc.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
+ subpassDesc.pColorAttachments = colorAttachmentRefs.data();
+ subpassDesc.pResolveAttachments = nullptr;
+ subpassDesc.pDepthStencilAttachment = (useDepth ? &depthStencilAttachmentRef : nullptr);
+ subpassDesc.preserveAttachmentCount = 0;
+ subpassDesc.pPreserveAttachments = nullptr;
+
+ VkRenderPassCreateInfo renderPassInfo;
+
+ renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassInfo.pNext = nullptr;
+ renderPassInfo.flags = 0;
+ renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescs.size());
+ renderPassInfo.pAttachments = attachmentDescs.data();
+ renderPassInfo.subpassCount = 1;
+ renderPassInfo.pSubpasses = &subpassDesc;
+ renderPassInfo.dependencyCount = 0;
+ renderPassInfo.pDependencies = nullptr;
+
+ vk::RenderPass renderPass(device);
+ ANGLE_TRY(renderPass.init(renderPassInfo));
+
+ mRenderPass = std::move(renderPass);
+
+ return &mRenderPass;
+}
+
+gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice device)
+{
+ // If we've already created our cached Framebuffer, return it.
+ if (mFramebuffer.valid())
+ {
+ return &mFramebuffer;
+ }
+
+ vk::RenderPass *renderPass = nullptr;
+ ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
+
+ // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
+ if (mBackbuffer)
+ {
+ return mBackbuffer->getCurrentFramebuffer(device, *renderPass);
+ }
+
+ // Gather VkImageViews over all FBO attachments, also size of attached region.
+ std::vector<VkImageView> attachments;
+ gl::Extents attachmentsSize;
+
+ const auto &colorAttachments = mState.getColorAttachments();
+ for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
+ {
+ const auto &colorAttachment = colorAttachments[attachmentIndex];
+ if (colorAttachment.isAttached())
+ {
+ RenderTargetVk *renderTarget = nullptr;
+ ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
+ attachments.push_back(renderTarget->imageView->getHandle());
+
+ ASSERT(attachmentsSize.empty() || attachmentsSize == colorAttachment.getSize());
+ attachmentsSize = colorAttachment.getSize();
+ }
+ }
+
+ const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
+ if (depthStencilAttachment && depthStencilAttachment->isAttached())
+ {
+ RenderTargetVk *renderTarget = nullptr;
+ ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
+ attachments.push_back(renderTarget->imageView->getHandle());
+
+ ASSERT(attachmentsSize.empty() || attachmentsSize == depthStencilAttachment->getSize());
+ attachmentsSize = depthStencilAttachment->getSize();
+ }
+
+ ASSERT(!attachments.empty());
+
+ VkFramebufferCreateInfo framebufferInfo;
+
+ framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ framebufferInfo.pNext = nullptr;
+ framebufferInfo.flags = 0;
+ framebufferInfo.renderPass = mRenderPass.getHandle();
+ framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
+ framebufferInfo.pAttachments = attachments.data();
+ framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
+ framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
+ framebufferInfo.layers = 1;
+
+ vk::Framebuffer framebuffer(device);
+ ANGLE_TRY(framebuffer.init(framebufferInfo));
+
+ mFramebuffer = std::move(framebuffer);
+
+ return &mFramebuffer;
}
gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const