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

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: Put back in present semaphore 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_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 DCHECK_EQ(static_cast<VkSemaphore>(VK_NULL_HANDLE), next_present_semaphore_);
20 }
21
22 bool VulkanSwapChain::Initialize(VkSurfaceKHR surface,
23 const VkSurfaceCapabilitiesKHR& surface_caps,
24 const VkSurfaceFormatKHR& surface_format) {
25 return InitializeSwapChain(surface, surface_caps, surface_format) &&
26 InitializeSwapImages(surface_caps, surface_format) &&
27 InitializeInitialBuffer();
28 }
29
30 void VulkanSwapChain::Destroy() {
31 DestroySwapImages();
32 DestroySwapChain();
33 }
34
35 gfx::SwapResult VulkanSwapChain::SwapBuffers() {
36 VkResult result = VK_SUCCESS;
37
38 VkDevice device = GetVulkanDevice();
39 VkQueue queue = GetVulkanQueue();
40
41 scoped_ptr<ImageData>& current_image_data = images_[current_image_];
42
43 // Default image subresource range.
44 VkImageSubresourceRange image_subresource_range = {};
45 image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
46 image_subresource_range.baseMipLevel = 0;
47 image_subresource_range.levelCount = 1;
48 image_subresource_range.baseArrayLayer = 0;
49 image_subresource_range.layerCount = 1;
50
51 // Make sure the current command buffer is not in use.
piman 2016/03/26 01:38:01 You need to do that before resetting/recording the
David Yen 2016/03/28 18:31:12 Right, I was trying to delay it to be as late as p
52 result = vkWaitForFences(device, 1,
53 &current_image_data->submission_fence,
54 VK_TRUE, UINT64_MAX);
55 if (VK_SUCCESS != result) {
56 DLOG(ERROR) << "vkWaitForFences() failed: " << result;
57 return gfx::SwapResult::SWAP_FAILED;
58 }
59
60 // Submit our command buffer for the current buffer.
61 if (!current_image_data->command_buffer->Submit(
62 queue, 1, &current_image_data->present_semaphore, 1,
63 &current_image_data->render_semaphore,
64 current_image_data->submission_fence)) {
65 return gfx::SwapResult::SWAP_FAILED;
66 }
67
68 // Queue the present.
69 VkPresentInfoKHR present_info = {};
70 present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
71 present_info.waitSemaphoreCount = 1;
72 present_info.pWaitSemaphores = &current_image_data->render_semaphore;
73 present_info.swapchainCount = 1;
74 present_info.pSwapchains = &swap_chain_;
75 present_info.pImageIndices = &current_image_;
76
77 result = vkQueuePresentKHR(queue, &present_info);
78 if (VK_SUCCESS != result) {
79 return gfx::SwapResult::SWAP_FAILED;
80 }
81
82 // Acquire then next image.
83 result = vkAcquireNextImageKHR(device, swap_chain_, UINT64_MAX,
84 next_present_semaphore_, VK_NULL_HANDLE,
85 &current_image_);
86 if (VK_SUCCESS != result) {
87 return gfx::SwapResult::SWAP_FAILED;
88 }
89
90 // Swap in the "next_present_semaphore" into the newly acquired image. The
91 // old "present_semaphore" for the image becomes the place holder for the next
92 // present semaphore for the next image.
93 scoped_ptr<ImageData>& next_image_data = images_[current_image_];
94 std::swap(next_image_data->present_semaphore, next_present_semaphore_);
95
96 return gfx::SwapResult::SWAP_ACK;
97 }
98
99 bool VulkanSwapChain::InitializeSwapChain(
100 VkSurfaceKHR surface,
101 const VkSurfaceCapabilitiesKHR& surface_caps,
102 const VkSurfaceFormatKHR& surface_format) {
103 VkDevice device = GetVulkanDevice();
104 VkResult result = VK_SUCCESS;
105
106 VkSwapchainCreateInfoKHR swap_chain_create_info = {};
107 swap_chain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
108 swap_chain_create_info.surface = surface;
109 swap_chain_create_info.minImageCount =
110 std::max(2u, surface_caps.minImageCount);
111 swap_chain_create_info.imageFormat = surface_format.format;
112 swap_chain_create_info.imageColorSpace = surface_format.colorSpace;
113 swap_chain_create_info.imageExtent = surface_caps.currentExtent;
114 swap_chain_create_info.imageArrayLayers = 1;
115 swap_chain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
116 swap_chain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
117 swap_chain_create_info.preTransform = surface_caps.currentTransform;
118 swap_chain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
119 swap_chain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
120 swap_chain_create_info.clipped = true;
121 swap_chain_create_info.oldSwapchain = swap_chain_;
122
123 VkSwapchainKHR new_swap_chain = VK_NULL_HANDLE;
124 result = vkCreateSwapchainKHR(device, &swap_chain_create_info, nullptr,
125 &new_swap_chain);
126 if (VK_SUCCESS != result) {
127 DLOG(ERROR) << "vkCreateSwapchainKHR() failed: " << result;
128 return false;
129 }
130
131 // Destroy the old swap chain and buffers.
132 // TODO(dyen): Look into how to do this safely while commands in flight.
133 Destroy();
134
135 swap_chain_ = new_swap_chain;
136 size_ = gfx::Size(swap_chain_create_info.imageExtent.width,
137 swap_chain_create_info.imageExtent.height);
138
139 return true;
140 }
141
142 void VulkanSwapChain::DestroySwapChain() {
143 VkDevice device = GetVulkanDevice();
144
145 if (swap_chain_ != VK_NULL_HANDLE) {
146 vkDestroySwapchainKHR(device, swap_chain_, nullptr);
147 swap_chain_ = VK_NULL_HANDLE;
148 }
149 }
150
151 bool VulkanSwapChain::InitializeSwapImages(
152 const VkSurfaceCapabilitiesKHR& surface_caps,
153 const VkSurfaceFormatKHR& surface_format) {
154 VkDevice device = GetVulkanDevice();
155 VkResult result = VK_SUCCESS;
156
157 uint32_t image_count = 0;
158 result = vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, nullptr);
159 if (VK_SUCCESS != result) {
160 DLOG(ERROR) << "vkGetSwapchainImagesKHR(NULL) failed: " << result;
161 return false;
162 }
163
164 std::vector<VkImage> images(image_count);
165 result =
166 vkGetSwapchainImagesKHR(device, swap_chain_, &image_count, images.data());
167 if (VK_SUCCESS != result) {
168 DLOG(ERROR) << "vkGetSwapchainImagesKHR(images) failed: " << result;
169 return false;
170 }
171
172 // Generic semaphore creation structure.
173 VkSemaphoreCreateInfo semaphore_create_info = {};
174 semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
175
176 // Generic fence creation structure.
177 VkFenceCreateInfo fence_create_info = {};
178 fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
179
180 // Default image subresource range.
181 VkImageSubresourceRange image_subresource_range = {};
182 image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
183 image_subresource_range.baseMipLevel = 0;
184 image_subresource_range.levelCount = 1;
185 image_subresource_range.baseArrayLayer = 0;
186 image_subresource_range.layerCount = 1;
187
188 // The image memory barrier is used to setup the image layout.
189 VkImageMemoryBarrier image_memory_barrier = {};
190 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
191 image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
jchen10 2016/03/28 07:47:23 Should we use VK_ACCESS_MEMORY_READ_BIT here for t
piman 2016/03/28 16:48:48 True, this is inconsistent. Actually, we're not al
David Yen 2016/03/28 18:31:12 Done. I can just queue the command for each comman
192 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
193 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
194 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
195 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
196 image_memory_barrier.subresourceRange = image_subresource_range;
197
198 command_pool_ = CreateCommandPool();
199 if (!command_pool_)
200 return false;
201
202 scoped_ptr<VulkanCommandBuffer> setup_command_buffer =
203 command_pool_->CreatePrimaryCommandBuffer();
204 if (!setup_command_buffer)
205 return false;
206
207 {
208 ScopedSingleUseCommandBufferRecorder recorder(*setup_command_buffer);
209 images_.resize(image_count);
210 for (uint32_t i = 0; i < image_count; ++i) {
211 images_[i].reset(new ImageData);
212 scoped_ptr<ImageData>& image_data = images_[i];
213 image_data->image = images[i];
214
215 // Setup semaphores.
216 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
217 &image_data->render_semaphore);
218 if (VK_SUCCESS != result) {
219 DLOG(ERROR) << "vkCreateSemaphore(render) failed: " << result;
220 return false;
221 }
222
223 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
224 &image_data->present_semaphore);
225 if (VK_SUCCESS != result) {
226 DLOG(ERROR) << "vkCreateSemaphore(present) failed: " << result;
227 return false;
228 }
229
230 result = vkCreateFence(device, &fence_create_info, nullptr,
231 &image_data->submission_fence);
piman 2016/03/26 01:38:01 Maybe you want to create these ones with VK_FENCE_
David Yen 2016/03/28 18:31:12 Done inside VulkanCommandBuffer. The implementatio
232 if (VK_SUCCESS != result) {
233 DLOG(ERROR) << "vkCreateFence(submission) failed: " << result;
234 return false;
235 }
236
237 // Setup the Image Layout.
238 image_memory_barrier.image = images[i];
239 vkCmdPipelineBarrier(recorder.handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
240 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
241 nullptr, 1, &image_memory_barrier);
242
243 // Create the image view.
244 image_data->image_view.reset(new VulkanImageView);
245 if (!image_data->image_view->Initialize(
246 images[i], VK_IMAGE_VIEW_TYPE_2D,
247 VulkanImageView::IMAGE_TYPE_COLOR, surface_format.format,
248 size_.width(), size_.height(), 0, 1, 0, 1)) {
249 return false;
250 }
251
252 // Initialize the command buffer for this buffer data.
253 image_data->command_buffer = command_pool_->CreatePrimaryCommandBuffer();
254 }
255 }
256
257 result = vkCreateSemaphore(device, &semaphore_create_info, nullptr,
258 &next_present_semaphore_);
259 if (VK_SUCCESS != result) {
260 DLOG(ERROR) << "vkCreateSemaphore(next_present) failed: " << result;
261 return false;
262 }
263
264 // Submit the image layout commands here.
265 VkFence layout_fence = VK_NULL_HANDLE;
266 result = vkCreateFence(device, &fence_create_info, nullptr, &layout_fence);
267 if (VK_SUCCESS != result) {
268 DLOG(ERROR) << "vkCreateFence(layout) failed: " << result;
269 return false;
270 }
271
272 // Submit the image layout commands, and tie them all to the render layout.
273 std::vector<VkSemaphore> initial_present_semaphores(image_count);
274 for (uint32_t i = 0; i < image_count; ++i) {
275 initial_present_semaphores[i] = images_[i]->present_semaphore;
276 }
277 if (!setup_command_buffer->Submit(GetVulkanQueue(), 0, nullptr, image_count,
278 initial_present_semaphores.data(),
279 layout_fence)) {
280 return false;
281 }
282
283 // TODO(dyen): Look into how we want to asynchronously check and clean up used
284 // command buffers. For now just wait until the fence passes. Eventually we
285 // probably want to store the fence somewhere and cleanup on a callback.
286 result = vkWaitForFences(device, 1, &layout_fence, VK_TRUE, UINT64_MAX);
287 if (VK_SUCCESS != result) {
288 DLOG(ERROR) << "vkWaitForFences() failed: " << result;
289 return false;
290 }
291
292 vkDestroyFence(device, layout_fence, nullptr);
293 setup_command_buffer->Destroy();
294 return true;
295 }
296
297 void VulkanSwapChain::DestroySwapImages() {
298 VkDevice device = GetVulkanDevice();
299
300 if (VK_NULL_HANDLE != next_present_semaphore_) {
301 vkDestroySemaphore(device, next_present_semaphore_, nullptr);
302 next_present_semaphore_ = VK_NULL_HANDLE;
303 }
304
305 for (const scoped_ptr<ImageData>& image_data : images_) {
306 if (image_data->command_buffer) {
307 image_data->command_buffer->Destroy();
308 image_data->command_buffer.reset();
309 }
310
311 // Destroy Image View.
312 if (image_data->image_view) {
313 image_data->image_view->Destroy();
314 image_data->image_view.reset();
315 }
316
317 // Destroy Semaphores/Fences.
318 if (VK_NULL_HANDLE != image_data->submission_fence) {
319 vkDestroyFence(device, image_data->submission_fence, nullptr);
320 image_data->submission_fence = VK_NULL_HANDLE;
321 }
322
323 if (VK_NULL_HANDLE != image_data->present_semaphore) {
324 vkDestroySemaphore(device, image_data->present_semaphore, nullptr);
325 image_data->present_semaphore = VK_NULL_HANDLE;
326 }
327
328 if (VK_NULL_HANDLE != image_data->render_semaphore) {
329 vkDestroySemaphore(device, image_data->render_semaphore, nullptr);
330 image_data->render_semaphore = VK_NULL_HANDLE;
331 }
332
333 image_data->image = VK_NULL_HANDLE;
334 }
335 images_.clear();
336
337 if (command_pool_) {
338 command_pool_->Destroy();
339 command_pool_.reset();
340 }
341 }
342
343 bool VulkanSwapChain::InitializeInitialBuffer() {
344 // Acquire the initial buffer, all the buffers have their initial render
345 // layout semaphore setup so this is a special case.
346 const VkResult result =
347 vkAcquireNextImageKHR(GetVulkanDevice(), swap_chain_, UINT64_MAX,
348 VK_NULL_HANDLE, VK_NULL_HANDLE, &current_image_);
349 if (VK_SUCCESS != result) {
350 DLOG(ERROR) << "vkAcquireNextImageKHR() failed: " << result;
351 return false;
352 }
353
354 return true;
355 }
356
357 VulkanSwapChain::ImageData::ImageData() {}
358
359 VulkanSwapChain::ImageData::~ImageData() {}
360
361 } // 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