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

Side by Side 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: removed unnecessary dependency 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/vulkan/vulkan_swap_chain.h"
6
7 #include "gpu/vulkan/vulkan_command_buffer.h"
8 #include "gpu/vulkan/vulkan_command_pool.h"
9 #include "gpu/vulkan/vulkan_image_view.h"
10 #include "gpu/vulkan/vulkan_implementation.h"
11
12 namespace gpu {
13
14 VulkanSwapChain::VulkanSwapChain() {}
15
16 VulkanSwapChain::~VulkanSwapChain() {
17 DCHECK(images_.empty());
18 DCHECK_EQ(static_cast<VkSwapchainKHR>(VK_NULL_HANDLE), swap_chain_);
19 }
20
21 bool VulkanSwapChain::Initialize(VkSurfaceKHR surface,
22 const VkSurfaceCapabilitiesKHR& surface_caps,
23 const VkSurfaceFormatKHR& surface_format) {
24 return InitializeSwapChain(surface, surface_caps, surface_format) &&
25 InitializeSwapImages(surface_caps, surface_format) &&
26 InitializeInitialBuffer();
27 }
28
29 void VulkanSwapChain::Destroy() {
30 DestroySwapImages();
31 DestroySwapChain();
32 }
33
34 gfx::SwapResult VulkanSwapChain::SwapBuffers() {
35 VkResult result = VK_SUCCESS;
36
37 scoped_ptr<ImageData>& current_image_data = images_[current_image_];
38
39 // Default image subresource range.
40 VkImageSubresourceRange image_subresource_range = {};
41 image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
42 image_subresource_range.baseMipLevel = 0;
43 image_subresource_range.levelCount = 1;
44 image_subresource_range.baseArrayLayer = 0;
45 image_subresource_range.layerCount = 1;
46
47 // Submit our command buffer for the current buffer.
48 if (!current_image_data->command_buffer->Submit(
49 GetVulkanQueue(), 0, nullptr, 1,
50 &current_image_data->render_semaphore)) {
piman 2016/03/25 02:01:27 You need a fence here, to know when you can reuse
David Yen 2016/03/25 17:36:14 Since vkAcquireNextImageKHR is blocking on the pre
piman 2016/03/25 21:13:22 That's not enough. The blocking that vkAcquireNext
David Yen 2016/03/26 00:33:30 Ok I see. I added the submission fence. Since the
piman 2016/03/26 01:38:01 Correct.
51 return gfx::SwapResult::SWAP_FAILED;
52 }
53
54 // Queue the present.
55 VkPresentInfoKHR present_info = {};
56 present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
57 present_info.waitSemaphoreCount = 1;
58 present_info.pWaitSemaphores = &current_image_data->render_semaphore;
59 present_info.swapchainCount = 1;
60 present_info.pSwapchains = &swap_chain_;
61 present_info.pImageIndices = &current_image_;
62
63 result = vkQueuePresentKHR(GetVulkanQueue(), &present_info);
64 if (VK_SUCCESS != result) {
65 return gfx::SwapResult::SWAP_FAILED;
66 }
67
68 // Setup for the next available buffer.
69 // TODO(dyen): Look into if this does what I'm expecting. More studying of
70 // the spec is required here. It doesn't seem clear if "success" when timeout
71 // is 0 means it will give you a buffer even before it's done presenting. That
72 // is probably what we want and the present/render_layout semaphore will
73 // do the synchronization for us.
piman 2016/03/25 02:01:26 We'll need a fence for throttling, though. Without
David Yen 2016/03/25 17:36:14 Wouldn't this call throttle by blocking if the nex
piman 2016/03/25 21:13:22 The presentation engine may very well never wait o
David Yen 2016/03/26 00:33:30 Acknowledged.
74 result = vkAcquireNextImageKHR(GetVulkanDevice(), swap_chain_, UINT64_MAX,
75 current_image_data->present_semaphore,
76 VK_NULL_HANDLE, &current_image_);
77 if (VK_SUCCESS != result) {
78 return gfx::SwapResult::SWAP_FAILED;
79 }
80
81 scoped_ptr<ImageData>& next_image_data = images_[current_image_];
82
83 // The present semaphore actually is associated with the new image data, but
84 // the previous one is guaranteed to be unused to swap it to the correct one.
85 std::swap(next_image_data->present_semaphore,
86 current_image_data->present_semaphore);
87
88 return gfx::SwapResult::SWAP_ACK;
89 }
90
91 bool VulkanSwapChain::InitializeSwapChain(
92 VkSurfaceKHR surface,
93 const VkSurfaceCapabilitiesKHR& surface_caps,
94 const VkSurfaceFormatKHR& surface_format) {
95 VkDevice device = GetVulkanDevice();
96 VkResult result = VK_SUCCESS;
97
98 VkSwapchainCreateInfoKHR swap_chain_create_info = {};
99 swap_chain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
100 swap_chain_create_info.surface = surface;
101 swap_chain_create_info.minImageCount =
102 std::max(2u, surface_caps.minImageCount);
103 swap_chain_create_info.imageFormat = surface_format.format;
104 swap_chain_create_info.imageColorSpace = surface_format.colorSpace;
105 swap_chain_create_info.imageExtent = surface_caps.currentExtent;
106 swap_chain_create_info.imageArrayLayers = 1;
107 swap_chain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
108 swap_chain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
109 swap_chain_create_info.preTransform = surface_caps.currentTransform;
110 swap_chain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
111 swap_chain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
112 swap_chain_create_info.clipped = true;
113 swap_chain_create_info.oldSwapchain = swap_chain_;
114
115 VkSwapchainKHR new_swap_chain = VK_NULL_HANDLE;
116 result = vkCreateSwapchainKHR(device, &swap_chain_create_info, nullptr,
117 &new_swap_chain);
118 if (VK_SUCCESS != result) {
119 DLOG(ERROR) << "vkCreateSwapchainKHR() failed: " << result;
120 return false;
121 }
122
123 // Destroy the old swap chain and buffers.
124 // TODO(dyen): Look into how to do this safely while commands in flight.
125 Destroy();
126
127 swap_chain_ = new_swap_chain;
128 size_ = gfx::Size(swap_chain_create_info.imageExtent.width,
129 swap_chain_create_info.imageExtent.height);
130
131 return true;
132 }
133
134 void VulkanSwapChain::DestroySwapChain() {
135 VkDevice device = GetVulkanDevice();
136
137 if (swap_chain_ != VK_NULL_HANDLE) {
138 vkDestroySwapchainKHR(device, swap_chain_, nullptr);
139 swap_chain_ = VK_NULL_HANDLE;
140 }
141 }
142
143 bool VulkanSwapChain::InitializeSwapImages(
144 const VkSurfaceCapabilitiesKHR& surface_caps,
145 const VkSurfaceFormatKHR& surface_format) {
146 VkDevice device = GetVulkanDevice();
147 VkResult result = VK_SUCCESS;
148
149 uint32_t image_count = 0;
150 result = vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, nullptr);
151 if (VK_SUCCESS != result) {
152 DLOG(ERROR) << "vkGetSwapchainImagesKHR(NULL) failed: " << result;
153 return false;
154 }
155
156 std::vector<VkImage> images(image_count);
157 result =
158 vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, images.data());
159 if (VK_SUCCESS != result) {
160 DLOG(ERROR) << "vkGetSwapchainImagesKHR(images) failed: " << result;
161 return false;
162 }
163
164 // Generic semaphore creation structure.
165 VkSemaphoreCreateInfo semaphore_create_info = {};
166 semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
167
168 // Default image subresource range.
169 VkImageSubresourceRange image_subresource_range = {};
170 image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
171 image_subresource_range.baseMipLevel = 0;
172 image_subresource_range.levelCount = 1;
173 image_subresource_range.baseArrayLayer = 0;
174 image_subresource_range.layerCount = 1;
175
176 // The image memory barrier is used to setup the image layout.
177 VkImageMemoryBarrier image_memory_barrier = {};
178 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
179 image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
180 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
181 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
182 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
183 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
184 image_memory_barrier.subresourceRange = image_subresource_range;
185
186 command_pool_ = CreateCommandPool();
187 if (!command_pool_)
188 return false;
189
190 scoped_ptr<VulkanCommandBuffer> setup_command_buffer =
191 command_pool_->CreatePrimaryCommandBuffer();
192 if (!setup_command_buffer)
193 return false;
194
195 {
196 ScopedSingleUseCommandBufferRecorder recorder(*setup_command_buffer);
197 images_.resize(image_count);
198 for (uint32_t i = 0; i < image_count; ++i) {
199 images_[i].reset(new ImageData);
200 scoped_ptr<ImageData>& image_data = images_[i];
201 image_data->image = images[i];
202
203 // Setup semaphores.
204 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
205 &image_data->render_semaphore);
206 if (VK_SUCCESS != result) {
207 DLOG(ERROR) << "vkCreateSemaphore(render) failed: " << result;
208 return false;
209 }
210
211 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
212 &image_data->present_semaphore);
213 if (VK_SUCCESS != result) {
214 DLOG(ERROR) << "vkCreateSemaphore(present) failed: " << result;
215 return false;
216 }
217
218 // Setup the Image Layout.
219 image_memory_barrier.image = images[i];
220 vkCmdPipelineBarrier(recorder.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
221 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
222 nullptr, 1, &image_memory_barrier);
223
224 // Create the image view.
225 image_data->image_view.reset(new VulkanImageView);
226 if (!image_data->image_view->Initialize(
227 images[i], VK_IMAGE_VIEW_TYPE_2D,
228 VulkanImageView::IMAGE_TYPE_COLOR, surface_format.format,
229 size_.width(), size_.height(), 0, 1, 0, 1)) {
230 return false;
231 }
232
233 // Initialize the command buffer for this buffer data.
234 image_data->command_buffer = command_pool_->CreatePrimaryCommandBuffer();
235 }
236 }
237
238 // Submit the image layout commands, and tie them all to the render layout.
239 std::vector<VkSemaphore> initial_present_semaphores(image_count);
240 for (uint32_t i = 0; i < image_count; ++i) {
241 initial_present_semaphores[i] = images_[i]->present_semaphore;
242 }
243 if (!setup_command_buffer->Submit(GetVulkanQueue(), 0, nullptr, image_count,
244 initial_present_semaphores.data())) {
245 return false;
246 }
247
248 // TODO(dyen): Look into how we want to asynchronously check and clean up used
249 // command buffers. For now just wait until the queue is idle so we can delete
250 // the command buffer from the stack.
251 result = vkQueueWaitIdle(GetVulkanQueue());
252 if (VK_SUCCESS != result) {
253 DLOG(ERROR) << "vkQueueWaitIdle() failed: " << result;
254 return false;
255 }
256
257 setup_command_buffer->Destroy();
258 return true;
259 }
260
261 void VulkanSwapChain::DestroySwapImages() {
262 VkDevice device = GetVulkanDevice();
263
264 for (const scoped_ptr<ImageData>& image_data : images_) {
265 if (image_data->command_buffer) {
266 image_data->command_buffer->Destroy();
267 image_data->command_buffer.reset();
268 }
269
270 // Destroy Image View.
271 if (image_data->image_view) {
272 image_data->image_view->Destroy();
273 image_data->image_view.reset();
274 }
275
276 // Destroy Semaphores.
277 if (VK_NULL_HANDLE != image_data->present_semaphore) {
278 vkDestroySemaphore(device, image_data->present_semaphore, nullptr);
279 image_data->present_semaphore = VK_NULL_HANDLE;
280 }
281
282 if (VK_NULL_HANDLE != image_data->render_semaphore) {
283 vkDestroySemaphore(device, image_data->render_semaphore, nullptr);
284 image_data->render_semaphore = VK_NULL_HANDLE;
285 }
286
287 image_data->image = VK_NULL_HANDLE;
288 }
289 images_.clear();
290
291 if (command_pool_) {
292 command_pool_->Destroy();
293 command_pool_.reset();
294 }
295 }
296
297 bool VulkanSwapChain::InitializeInitialBuffer() {
298 // Acquire the initial buffer, all the buffers have their initial render
299 // layout semaphore setup so this is a special case.
300 const VkResult result =
301 vkAcquireNextImageKHR(GetVulkanDevice(), swap_chain_, UINT64_MAX,
302 VK_NULL_HANDLE, VK_NULL_HANDLE, &current_image_);
303 if (VK_SUCCESS != result) {
304 DLOG(ERROR) << "vkAcquireNextImageKHR() failed: " << result;
305 return false;
306 }
307
308 return true;
309 }
310
311 VulkanSwapChain::ImageData::ImageData() {}
312
313 VulkanSwapChain::ImageData::~ImageData() {}
314
315 } // namespace gpu
OLDNEW
« gpu/vulkan/vulkan_render_pass.cc ('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