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

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: rebase 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
« no previous file with comments | « gpu/vulkan/vulkan_swap_chain.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_implementation.h"
10
11 namespace gpu {
12
13 VulkanSwapChain::VulkanSwapChain() {}
14
15 VulkanSwapChain::~VulkanSwapChain() {
16 DCHECK(images_.empty());
17 DCHECK_EQ(static_cast<VkSwapchainKHR>(VK_NULL_HANDLE), swap_chain_);
18 }
19
20 bool VulkanSwapChain::Initialize(VkSurfaceKHR surface,
21 const VkSurfaceCapabilitiesKHR& surface_caps,
22 const VkSurfaceFormatKHR& surface_format) {
23 return InitializeSwapChain(surface, surface_caps, surface_format) &&
24 InitializeImageLayoutCommandBuffer() &&
25 InitializeSwapImages(surface_caps, surface_format) &&
26 InitializeInitialBuffer();
27 }
28
29 void VulkanSwapChain::Destroy() {
30 DestroySwapImages();
31 DestroyImageLayoutCommandBuffer();
32 DestroySwapChain();
33 }
34
35 gfx::SwapResult VulkanSwapChain::SwapBuffers() {
36 VkResult result = VK_SUCCESS;
37
38 scoped_ptr<ImageData>& current_image_data = images_[current_image_];
39
40 // Default image subresource range.
41 VkImageSubresourceRange image_subresource_range = {};
42 image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
43 image_subresource_range.baseMipLevel = 0;
44 image_subresource_range.levelCount = 1;
45 image_subresource_range.baseArrayLayer = 0;
46 image_subresource_range.layerCount = 1;
47
48 // Submit our command buffer for the current buffer.
49 if (!current_image_data->command_buffer->Submit(
50 GetVulkanQueue(), 1, &current_image_data->render_layout_semaphore, 1,
51 &current_image_data->render_semaphore)) {
52 return gfx::SwapResult::SWAP_FAILED;
53 }
54
55 // Prepare the image layout to present.
56 {
57 ScopedSingleUseCommandBufferRecorder recorder(
58 *image_layout_command_buffer_);
59
60 VkImageMemoryBarrier image_memory_barrier = {};
61 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
62 image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
63 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
64 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
65 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
66 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
67 image_memory_barrier.subresourceRange = image_subresource_range;
68 image_memory_barrier.image = current_image_data->image;
69
70 vkCmdPipelineBarrier(recorder.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
71 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
72 nullptr, 1, &image_memory_barrier);
73 }
74 if (!image_layout_command_buffer_->Submit(
75 GetVulkanQueue(), 1, &current_image_data->render_semaphore, 1,
76 &current_image_data->present_layout_semaphore)) {
77 return gfx::SwapResult::SWAP_FAILED;
78 }
79
80 // Queue the present.
81 VkPresentInfoKHR present_info = {};
82 present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
83 present_info.waitSemaphoreCount = 1;
84 present_info.pWaitSemaphores = &current_image_data->present_layout_semaphore;
85 present_info.swapchainCount = 1;
86 present_info.pSwapchains = &swap_chain_;
87 present_info.pImageIndices = &current_image_;
88
89 result = vkQueuePresentKHR(GetVulkanQueue(), &present_info);
90 if (VK_SUCCESS != result) {
91 return gfx::SwapResult::SWAP_FAILED;
92 }
93
94 // Setup for the next available buffer.
95 // TODO(dyen): Look into if this does what I'm expecting. More studying of
96 // the spec is required here. It doesn't seem clear if "success" when timeout
97 // is 0 means it will give you a buffer even before it's done presenting. That
98 // is probably what we want and the present/render_layout semaphore will
99 // do the synchronization for us.
100 result = vkAcquireNextImageKHR(GetVulkanDevice(), swap_chain_, 0,
101 current_image_data->present_semaphore,
David Yen 2016/03/10 02:19:38 Hmm... looking at this code again I'm unclear whic
David Yen 2016/03/11 00:59:46 Chatted separately. This semaphore and the followi
102 VK_NULL_HANDLE, &current_image_);
103 if (VK_SUCCESS != result) {
104 return gfx::SwapResult::SWAP_FAILED;
105 }
106
107 // Setup the previous layout back to the render layout after presentation.
108 {
109 ScopedSingleUseCommandBufferRecorder recorder(
110 *image_layout_command_buffer_);
111
112 VkImageMemoryBarrier image_memory_barrier = {};
113 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
114 image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
115 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
116 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
117 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
118 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
119 image_memory_barrier.subresourceRange = image_subresource_range;
120 image_memory_barrier.image = current_image_data->image;
121
122 vkCmdPipelineBarrier(recorder.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
123 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
124 nullptr, 1, &image_memory_barrier);
125 }
126 // TODO(dyen): This signals render_layout_semaphore which is waited upon
127 // above. When this submit is called it is possible the render layout
128 // semaphore is in an unsignalled state, however by the time the present
129 // semaphore is signalled it is guaranteed to be in an unsignalled state.
130 // We need to make sure this is ok, the spec doesn't specify any constraints
131 // here.
132 if (!image_layout_command_buffer_->Submit(
133 GetVulkanQueue(), 1, &current_image_data->present_semaphore, 1,
134 &current_image_data->render_layout_semaphore)) {
135 return gfx::SwapResult::SWAP_FAILED;
136 }
137
138 return gfx::SwapResult::SWAP_ACK;
139 }
140
141 bool VulkanSwapChain::InitializeSwapChain(
142 VkSurfaceKHR surface,
143 const VkSurfaceCapabilitiesKHR& surface_caps,
144 const VkSurfaceFormatKHR& surface_format) {
145 VkDevice device = GetVulkanDevice();
146 VkResult result = VK_SUCCESS;
147
148 VkSwapchainCreateInfoKHR swap_chain_create_info = {};
149 swap_chain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
150 swap_chain_create_info.surface = surface;
151 swap_chain_create_info.minImageCount =
152 std::min(2u, surface_caps.maxImageCount);
153 swap_chain_create_info.imageFormat = surface_format.format;
154 swap_chain_create_info.imageColorSpace = surface_format.colorSpace;
155 swap_chain_create_info.imageExtent = surface_caps.currentExtent;
156 swap_chain_create_info.imageArrayLayers = 1;
157 swap_chain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
158 swap_chain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
159 swap_chain_create_info.preTransform = surface_caps.currentTransform;
160 swap_chain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
161 swap_chain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
162 swap_chain_create_info.clipped = true;
163 swap_chain_create_info.oldSwapchain = swap_chain_;
164
165 VkSwapchainKHR new_swap_chain = VK_NULL_HANDLE;
166 result = vkCreateSwapchainKHR(device, &swap_chain_create_info, nullptr,
167 &new_swap_chain);
168 if (VK_SUCCESS != result) {
169 DLOG(ERROR) << "vkCreateSwapchainKHR() failed: " << result;
170 return false;
171 }
172
173 // Destroy the old swap chain and buffers.
174 // TODO(dyen): Look into how to do this safely while commands in flight.
175 Destroy();
176
177 swap_chain_ = new_swap_chain;
178 return true;
179 }
180
181 void VulkanSwapChain::DestroySwapChain() {
182 VkDevice device = GetVulkanDevice();
183
184 if (swap_chain_ != VK_NULL_HANDLE) {
185 vkDestroySwapchainKHR(device, swap_chain_, nullptr);
186 swap_chain_ = VK_NULL_HANDLE;
187 }
188 }
189
190 bool VulkanSwapChain::InitializeImageLayoutCommandBuffer() {
191 command_pool_ = CreateCommandPool();
192 if (!command_pool_)
193 return false;
194
195 image_layout_command_buffer_ = command_pool_->CreatePrimaryCommandBuffer();
196 if (!image_layout_command_buffer_)
197 return false;
198
199 return true;
200 }
201
202 void VulkanSwapChain::DestroyImageLayoutCommandBuffer() {
203 if (image_layout_command_buffer_) {
204 image_layout_command_buffer_->Destroy();
205 image_layout_command_buffer_.reset();
206 }
207
208 if (command_pool_) {
209 command_pool_->Destroy();
210 command_pool_.reset();
211 }
212 }
213
214 bool VulkanSwapChain::InitializeSwapImages(
215 const VkSurfaceCapabilitiesKHR& surface_caps,
216 const VkSurfaceFormatKHR& surface_format) {
217 VkDevice device = GetVulkanDevice();
218 VkResult result = VK_SUCCESS;
219
220 uint32_t image_count = 0;
221 result = vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, nullptr);
222 if (VK_SUCCESS != result) {
223 DLOG(ERROR) << "vkGetSwapchainImagesKHR(NULL) failed: " << result;
224 return false;
225 }
226
227 std::vector<VkImage> images(image_count);
228 result =
229 vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, images.data());
230 if (VK_SUCCESS != result) {
231 DLOG(ERROR) << "vkGetSwapchainImagesKHR(images) failed: " << result;
232 return false;
233 }
234
235 // Generic semaphore creation structure.
236 VkSemaphoreCreateInfo semaphore_create_info = {};
237 semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
238
239 // Default image subresource range.
240 VkImageSubresourceRange image_subresource_range = {};
241 image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
242 image_subresource_range.baseMipLevel = 0;
243 image_subresource_range.levelCount = 1;
244 image_subresource_range.baseArrayLayer = 0;
245 image_subresource_range.layerCount = 1;
246
247 // The image memory barrier is used to setup the image layout.
248 VkImageMemoryBarrier image_memory_barrier = {};
249 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
250 image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
251 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
252 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
253 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
254 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
255 image_memory_barrier.subresourceRange = image_subresource_range;
256
257 // We must create an image view for each image.
258 VkImageViewCreateInfo image_view_create_info = {};
259 image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
260 image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
261 image_view_create_info.format = surface_format.format;
262 image_view_create_info.components = {
263 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
264 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
265 image_view_create_info.subresourceRange = image_subresource_range;
266
267 {
268 ScopedSingleUseCommandBufferRecorder recorder(
269 *image_layout_command_buffer_);
270 images_.resize(image_count);
271 for (uint32_t i = 0; i < image_count; ++i) {
272 images_[i].reset(new ImageData);
273 scoped_ptr<ImageData>& image_data = images_[i];
274 image_data->image = images[i];
275
276 // Setup semaphores.
277 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
278 &image_data->render_layout_semaphore);
279 if (VK_SUCCESS != result) {
280 DLOG(ERROR) << "vkCreateSemaphore(render_layout) failed: " << result;
281 return false;
282 }
283 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
284 &image_data->render_semaphore);
285 if (VK_SUCCESS != result) {
286 DLOG(ERROR) << "vkCreateSemaphore(render) failed: " << result;
287 return false;
288 }
289
290 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
291 &image_data->present_layout_semaphore);
292 if (VK_SUCCESS != result) {
293 DLOG(ERROR) << "vkCreateSemaphore(present_layout) failed: " << result;
294 return false;
295 }
296
297 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
298 &image_data->present_semaphore);
299 if (VK_SUCCESS != result) {
300 DLOG(ERROR) << "vkCreateSemaphore(present) failed: " << result;
301 return false;
302 }
303
304 // Setup the Image Layout.
305 image_memory_barrier.image = images[i];
306 vkCmdPipelineBarrier(recorder.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
307 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
308 nullptr, 1, &image_memory_barrier);
309
310 // Create the image view.
311 image_view_create_info.image = images[i];
312 result = vkCreateImageView(device, &image_view_create_info, nullptr,
313 &image_data->image_view);
314 if (VK_SUCCESS != result) {
315 DLOG(ERROR) << "vkCreateImageView() failed: " << result;
316 return false;
317 }
318
319 // Initialize the command buffer for this buffer data.
320 image_data->command_buffer = command_pool_->CreatePrimaryCommandBuffer();
321 }
322 }
323
324 // Submit the image layout commands, and tie them all to the render layout.
325 std::vector<VkSemaphore> initial_render_layout_semaphores(image_count);
326 for (uint32_t i = 0; i < image_count; ++i) {
327 initial_render_layout_semaphores[i] = images_[i]->render_layout_semaphore;
328 }
329 if (!image_layout_command_buffer_->Submit(
330 GetVulkanQueue(), 0, nullptr, image_count,
331 initial_render_layout_semaphores.data())) {
332 return false;
333 }
334
335 return true;
336 }
337
338 void VulkanSwapChain::DestroySwapImages() {
339 VkDevice device = GetVulkanDevice();
340
341 for (const scoped_ptr<ImageData>& image_data : images_) {
342 if (image_data->command_buffer) {
343 image_data->command_buffer->Destroy();
344 image_data->command_buffer.reset();
345 }
346
347 // Destroy Image View.
348 if (VK_NULL_HANDLE != image_data->image_view) {
349 vkDestroyImageView(device, image_data->image_view, nullptr);
350 image_data->image_view = VK_NULL_HANDLE;
351 }
352
353 // Destroy Semaphores.
354 if (VK_NULL_HANDLE != image_data->present_semaphore) {
355 vkDestroySemaphore(device, image_data->present_semaphore, nullptr);
356 image_data->present_semaphore = VK_NULL_HANDLE;
357 }
358
359 if (VK_NULL_HANDLE != image_data->present_layout_semaphore) {
360 vkDestroySemaphore(device, image_data->present_layout_semaphore, nullptr);
361 image_data->present_layout_semaphore = VK_NULL_HANDLE;
362 }
363
364 if (VK_NULL_HANDLE != image_data->render_semaphore) {
365 vkDestroySemaphore(device, image_data->render_semaphore, nullptr);
366 image_data->render_semaphore = VK_NULL_HANDLE;
367 }
368
369 if (VK_NULL_HANDLE != image_data->render_layout_semaphore) {
370 vkDestroySemaphore(device, image_data->render_layout_semaphore, nullptr);
371 image_data->render_layout_semaphore = VK_NULL_HANDLE;
372 }
373
374 image_data->image = VK_NULL_HANDLE;
375 }
376 images_.clear();
377 }
378
379 bool VulkanSwapChain::InitializeInitialBuffer() {
380 // Acquire the initial buffer, all the buffers have their initial render
381 // layout semaphore setup so this is a special case.
382 const VkResult result =
383 vkAcquireNextImageKHR(GetVulkanDevice(), swap_chain_, 0, VK_NULL_HANDLE,
384 VK_NULL_HANDLE, &current_image_);
385 if (VK_SUCCESS != result) {
386 DLOG(ERROR) << "vkAcquireNextImageKHR() failed: " << result;
387 return false;
388 }
389
390 return true;
391 }
392
393 VulkanSwapChain::ImageData::ImageData() {}
394
395 VulkanSwapChain::ImageData::~ImageData() {}
396
397 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/vulkan/vulkan_swap_chain.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698