Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(751)

Unified Diff: gpu/vulkan/vulkan_swap_chain.cc

Issue 1776453003: Added initial implementation of Vulkan Render Passes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gn_vulkan
Patch Set: Ensure vulkan handles all initialized to null, check destruction in destructor Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« gpu/vulkan/vulkan_swap_chain.h ('K') | « gpu/vulkan/vulkan_swap_chain.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/vulkan/vulkan_swap_chain.cc
diff --git a/gpu/vulkan/vulkan_swap_chain.cc b/gpu/vulkan/vulkan_swap_chain.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fc7c39d589a8beb03cac4bb79956b715d69967c7
--- /dev/null
+++ b/gpu/vulkan/vulkan_swap_chain.cc
@@ -0,0 +1,241 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/vulkan/vulkan_swap_chain.h"
+
+#include "gpu/vulkan/vulkan_implementation.h"
+
+namespace gfx {
+
+VulkanSwapChain::VulkanSwapChain() {}
+
+VulkanSwapChain::~VulkanSwapChain() {
+ DCHECK(buffers_.empty());
+ DCHECK_EQ(static_cast<VkSwapchainKHR>(VK_NULL_HANDLE), swap_chain_);
+ DCHECK_EQ(static_cast<VkRenderPass>(VK_NULL_HANDLE), render_pass_);
+}
+
+bool VulkanSwapChain::Initialize(VkCommandBuffer command_buffer,
+ VkSurfaceKHR surface,
+ const VkSurfaceCapabilitiesKHR& surface_caps,
+ const VkSurfaceFormatKHR& surface_format,
+ const VkComponentMapping& view_mapping) {
+ return InitializeSwapChain(surface, surface_caps, surface_format) &&
+ InitializeRenderPass(surface_format) &&
+ InitializeSwapBuffers(command_buffer, surface_caps, surface_format,
+ view_mapping);
+}
+
+void VulkanSwapChain::Destroy() {
+ VkDevice device = GetVulkanDevice();
+
+ for (const scoped_ptr<BufferData>& buffer_data : buffers_) {
+ if (buffer_data->command_buffer) {
+ buffer_data->command_buffer->Destroy();
+ buffer_data->command_buffer.reset();
+ }
+
+ vkDestroyFramebuffer(device, buffer_data->frame_buffer, nullptr);
+ buffer_data->frame_buffer = VK_NULL_HANDLE;
+
+ vkDestroyImageView(device, buffer_data->image_view, nullptr);
+ buffer_data->image_view = VK_NULL_HANDLE;
+ buffer_data->image = VK_NULL_HANDLE;
+ }
+ buffers_.clear();
+
+ if (render_pass_ != VK_NULL_HANDLE) {
+ vkDestroyRenderPass(device, render_pass_, nullptr);
+ render_pass_ = VK_NULL_HANDLE;
+ }
+
+ if (swap_chain_ != VK_NULL_HANDLE) {
+ vkDestroySwapchainKHR(device, swap_chain_, nullptr);
+ swap_chain_ = VK_NULL_HANDLE;
+ }
+}
+
+void VulkanSwapChain::SwapBuffers() {
+ current_buffer_ = (current_buffer_ + 1) % buffers_.size();
+}
+
+bool VulkanSwapChain::InitializeSwapChain(
+ VkSurfaceKHR surface,
+ const VkSurfaceCapabilitiesKHR& surface_caps,
+ const VkSurfaceFormatKHR& surface_format) {
+ VkDevice device = GetVulkanDevice();
+ VkResult result = VK_SUCCESS;
+
+ VkSwapchainCreateInfoKHR swap_chain_create_info = {};
+ swap_chain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swap_chain_create_info.surface = surface;
+ swap_chain_create_info.minImageCount =
+ std::max(surface_caps.minImageCount + 1, surface_caps.maxImageCount);
piman 2016/03/09 01:25:34 We shouldn't need +1, because we shouldn't be keep
David Yen 2016/03/10 01:39:49 Oops, I meant std::min here. I was assuming minIma
+ swap_chain_create_info.imageFormat = surface_format.format;
+ swap_chain_create_info.imageColorSpace = surface_format.colorSpace;
+ swap_chain_create_info.imageExtent = surface_caps.currentExtent;
+ swap_chain_create_info.imageArrayLayers = 1;
+ swap_chain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swap_chain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swap_chain_create_info.preTransform = surface_caps.currentTransform;
+ swap_chain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ swap_chain_create_info.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
piman 2016/03/09 01:25:35 VK_PRESENT_MODE_FIFO_KHR 1- that's the only one t
David Yen 2016/03/10 01:39:49 Done.
+ swap_chain_create_info.clipped = true;
+ swap_chain_create_info.oldSwapchain = swap_chain_;
+
+ VkSwapchainKHR new_swap_chain = VK_NULL_HANDLE;
+ result = vkCreateSwapchainKHR(device, &swap_chain_create_info, nullptr,
+ &new_swap_chain);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkCreateSwapchainKHR() failed: " << result;
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ return false;
+ }
+
+ // Destroy the old swap chain and buffers.
+ // TODO(dyen): Look into how to do this safely while commands in flight.
piman 2016/03/09 01:25:34 Right, at the very least we need to wait for previ
David Yen 2016/03/10 01:39:49 I will worry about this when I look into how to sa
+ Destroy();
+
+ swap_chain_ = new_swap_chain;
+ return true;
+}
+
+bool VulkanSwapChain::InitializeRenderPass(
piman 2016/03/09 01:25:35 I don't feel like this belongs to the SwapChain. E
David Yen 2016/03/10 01:39:49 Done.
+ const VkSurfaceFormatKHR& surface_format) {
+ VkAttachmentDescription attachment_description = {};
+ attachment_description.format = surface_format.format;
+ attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
+ attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachment_description.initialLayout =
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachment_description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
piman 2016/03/09 01:25:34 It would be useful to do the transition to VK_IMAG
David Yen 2016/03/10 01:39:49 RenderPass no longer in this CL, I'll make a note
+
+ VkAttachmentReference color_attachment_reference = {};
+ color_attachment_reference.attachment = 0;
+ color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass_description = {};
+ subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass_description.colorAttachmentCount = 1;
+ subpass_description.pColorAttachments = &color_attachment_reference;
+
+ VkRenderPassCreateInfo render_pass_create_info = {};
+ render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ render_pass_create_info.attachmentCount = 1;
+ render_pass_create_info.pAttachments = &attachment_description;
+ render_pass_create_info.subpassCount = 1;
+ render_pass_create_info.pSubpasses = &subpass_description;
+
+ VkResult result = vkCreateRenderPass(
+ GetVulkanDevice(), &render_pass_create_info, nullptr, &render_pass_);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkCreateRenderPass() failed: " << result;
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ return false;
+ }
+
+ return true;
+}
+
+bool VulkanSwapChain::InitializeSwapBuffers(
+ VkCommandBuffer command_buffer,
+ const VkSurfaceCapabilitiesKHR& surface_caps,
+ const VkSurfaceFormatKHR& surface_format,
+ const VkComponentMapping& view_mapping) {
+ VkDevice device = GetVulkanDevice();
+ VkResult result = VK_SUCCESS;
+
+ uint32_t buffer_count = 0;
+ result = vkGetSwapchainImagesKHR(device, swap_chain_, &buffer_count, nullptr);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkGetSwapchainImagesKHR(NULL) failed: " << result;
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ return false;
+ }
+
+ std::vector<VkImage> images(buffer_count);
+ result = vkGetSwapchainImagesKHR(device, swap_chain_, &buffer_count,
+ images.data());
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkGetSwapchainImagesKHR(images) failed: " << result;
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ return false;
+ }
+
+ // Default image subresource range.
+ VkImageSubresourceRange image_subresource_range = {};
+ image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ image_subresource_range.baseMipLevel = 0;
+ image_subresource_range.levelCount = 1;
+ image_subresource_range.baseArrayLayer = 0;
+ image_subresource_range.layerCount = 1;
+
+ // The image memory barrier is used to setup the image layout.
+ VkImageMemoryBarrier image_memory_barrier = {};
+ image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ image_memory_barrier.srcAccessMask =
+ VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
piman 2016/03/09 01:25:35 I don't think either of these flags is useful: - w
David Yen 2016/03/10 01:39:49 Done.
+ image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.subresourceRange = image_subresource_range;
+
+ // We must create an image view for each image.
+ VkImageViewCreateInfo image_view_create_info = {};
+ image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ image_view_create_info.format = surface_format.format;
+ image_view_create_info.components = view_mapping;
piman 2016/03/09 01:25:34 For a render target view, the VkComponentMapping n
David Yen 2016/03/10 01:39:49 Done.
+ image_view_create_info.subresourceRange = image_subresource_range;
+
+ // Frame buffer creation info.
piman 2016/03/09 01:25:34 For the same reason as the RenderPass, I think we
David Yen 2016/03/10 01:39:49 Ok, I was originally thinking we could just have d
+ VkFramebufferCreateInfo frame_buffer_create_info = {};
+ frame_buffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ frame_buffer_create_info.renderPass = render_pass_;
+ frame_buffer_create_info.attachmentCount = 1;
+ frame_buffer_create_info.width = surface_caps.currentExtent.width;
+ frame_buffer_create_info.height = surface_caps.currentExtent.height;
+ frame_buffer_create_info.layers = 1;
+
+ buffers_.resize(buffer_count);
+ for (uint32_t i = 0; i < buffer_count; ++i) {
+ buffers_[i].reset(new BufferData);
+ buffers_[i]->image = images[i];
+
+ // Setup the Image Layout.
+ image_memory_barrier.image = images[i];
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
piman 2016/03/09 01:25:34 If the intent is for this to happen before renderi
David Yen 2016/03/10 01:39:49 So I was envisioning every image to be in "PRESENT
+ nullptr, 1, &image_memory_barrier);
+
+ // Create the image view.
+ image_view_create_info.image = images[i];
+ result = vkCreateImageView(device, &image_view_create_info, nullptr,
+ &buffers_[i]->image_view);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkCreateImageView() failed: " << result;
piman 2016/03/09 01:25:35 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ return false;
+ }
+
+ // Create the frame buffer.
+ frame_buffer_create_info.pAttachments = &buffers_[i]->image_view;
+ result = vkCreateFramebuffer(device, &frame_buffer_create_info, nullptr,
+ &buffers_[i]->frame_buffer);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkCreateFramebuffer() failed: " << result;
piman 2016/03/09 01:25:35 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ return false;
+ }
+
+ // Initialize the command buffer for this buffer data.
+ buffers_[i]->command_buffer = CreatePrimaryCommandBuffer();
+ }
+
+ return true;
+}
+
+VulkanSwapChain::BufferData::BufferData() {}
+
+VulkanSwapChain::BufferData::~BufferData() {}
+
+} // namespace gfx
« gpu/vulkan/vulkan_swap_chain.h ('K') | « gpu/vulkan/vulkan_swap_chain.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698