OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2015 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 #include "GrContext.h" | |
10 #include "SkSurface.h" | |
11 #include "VulkanTestContext.h" | |
12 | |
13 #include "vk/GrVkInterface.h" | |
14 #include "vk/GrVkUtil.h" | |
15 #include "vk/GrVkTypes.h" | |
16 | |
17 #ifdef VK_USE_PLATFORM_WIN32_KHR | |
18 // windows wants to define this as CreateSemaphoreA or CreateSemaphoreW | |
19 #undef CreateSemaphore | |
20 #endif | |
21 | |
22 #define GET_PROC(F) f ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk"
#F) | |
23 #define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk"
#F) | |
24 | |
25 VulkanTestContext::VulkanTestContext(void* platformData, int msaaSampleCount) | |
26 : fSurface(VK_NULL_HANDLE) | |
27 , fSwapchain(VK_NULL_HANDLE) | |
28 , fCommandPool(VK_NULL_HANDLE) | |
29 , fBackbuffers(nullptr) { | |
30 | |
31 // any config code here (particularly for msaa)? | |
32 | |
33 this->initializeContext(platformData); | |
34 } | |
35 | |
36 void VulkanTestContext::initializeContext(void* platformData) { | |
37 | |
38 fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPre
sent)); | |
39 if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) || | |
40 !(fBackendContext->fExtensions & kKHR_swapchain_GrVkExtensionFlag)) { | |
41 fBackendContext.reset(nullptr); | |
42 return; | |
43 } | |
44 | |
45 VkInstance instance = fBackendContext->fInstance; | |
46 VkDevice device = fBackendContext->fDevice; | |
47 GET_PROC(DestroySurfaceKHR); | |
48 GET_PROC(GetPhysicalDeviceSurfaceSupportKHR); | |
49 GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR); | |
50 GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR); | |
51 GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR); | |
52 GET_DEV_PROC(CreateSwapchainKHR); | |
53 GET_DEV_PROC(DestroySwapchainKHR); | |
54 GET_DEV_PROC(GetSwapchainImagesKHR); | |
55 GET_DEV_PROC(AcquireNextImageKHR); | |
56 GET_DEV_PROC(QueuePresentKHR); | |
57 | |
58 fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext)fBackendCo
ntext.get()); | |
59 | |
60 fSurface = createVkSurface(instance, platformData); | |
61 if (VK_NULL_HANDLE == fSurface) { | |
62 fBackendContext.reset(nullptr); | |
63 return; | |
64 } | |
65 | |
66 VkBool32 supported; | |
67 VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fBackendContext->fPhysica
lDevice, | |
68 fPresentQueueIndex, fSurf
ace, | |
69 &supported); | |
70 if (VK_SUCCESS != res) { | |
71 this->destroyContext(); | |
72 return; | |
73 } | |
74 | |
75 if (!this->createSwapchain(-1, -1)) { | |
76 this->destroyContext(); | |
77 return; | |
78 } | |
79 | |
80 // create presentQueue | |
81 vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQ
ueue); | |
82 } | |
83 | |
84 bool VulkanTestContext::createSwapchain(uint32_t width, uint32_t height) | |
85 { | |
86 // check for capabilities | |
87 VkSurfaceCapabilitiesKHR caps; | |
88 VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fBackendContext->fPh
ysicalDevice, | |
89 fSurface, &caps); | |
90 if (VK_SUCCESS != res) { | |
91 return false; | |
92 } | |
93 | |
94 uint32_t surfaceFormatCount; | |
95 res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice,
fSurface, | |
96 &surfaceFormatCount, nullptr); | |
97 if (VK_SUCCESS != res) { | |
98 return false; | |
99 } | |
100 | |
101 SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatK
HR)); | |
102 VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc
.get(); | |
103 res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice,
fSurface, | |
104 &surfaceFormatCount, surfaceFormat
s); | |
105 if (VK_SUCCESS != res) { | |
106 return false; | |
107 } | |
108 | |
109 uint32_t presentModeCount; | |
110 res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDev
ice, fSurface, | |
111 &presentModeCount, nullptr); | |
112 if (VK_SUCCESS != res) { | |
113 return false; | |
114 } | |
115 | |
116 SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR)); | |
117 VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get(); | |
118 res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDev
ice, fSurface, | |
119 &presentModeCount, presentMo
des); | |
120 if (VK_SUCCESS != res) { | |
121 return false; | |
122 } | |
123 | |
124 VkExtent2D extent = caps.currentExtent; | |
125 // use the hints | |
126 if (extent.width == (uint32_t)-1) { | |
127 extent.width = width; | |
128 extent.height = height; | |
129 } | |
130 | |
131 // clamp width; to protect us from broken hints | |
132 if (extent.width < caps.minImageExtent.width) { | |
133 extent.width = caps.minImageExtent.width; | |
134 } else if (extent.width > caps.maxImageExtent.width) { | |
135 extent.width = caps.maxImageExtent.width; | |
136 } | |
137 // clamp height | |
138 if (extent.height < caps.minImageExtent.height) { | |
139 extent.height = caps.minImageExtent.height; | |
140 } else if (extent.height > caps.maxImageExtent.height) { | |
141 extent.height = caps.maxImageExtent.height; | |
142 } | |
143 fWidth = (int)extent.width; | |
144 fHeight = (int)extent.height; | |
145 | |
146 uint32_t imageCount = caps.minImageCount + 2; | |
147 if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) { | |
148 // Application must settle for fewer images than desired: | |
149 imageCount = caps.maxImageCount; | |
150 } | |
151 | |
152 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | | |
153 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | | |
154 VK_IMAGE_USAGE_TRANSFER_DST_BIT; | |
155 SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags); | |
156 SkASSERT(caps.supportedTransforms & caps.currentTransform); | |
157 SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | | |
158 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
); | |
159 VkCompositeAlphaFlagBitsKHR composite_alpha = | |
160 (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ? | |
161 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR : | |
162 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; | |
163 | |
164 // Pick our surface format -- for now, the first one | |
165 VkFormat surfaceFormat = surfaceFormats[0].format; | |
166 VkColorSpaceKHR colorSpace = surfaceFormats[0].colorSpace; | |
167 | |
168 // If mailbox mode is available, use it, as it is the lowest-latency non- | |
169 // tearing mode. If not, fall back to FIFO which is always available. | |
170 VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR; | |
171 for (uint32_t i = 0; i < presentModeCount; ++i) { | |
172 // use mailbox | |
173 if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) { | |
174 mode = presentModes[i]; | |
175 break; | |
176 } | |
177 } | |
178 | |
179 VkSwapchainCreateInfoKHR swapchainCreateInfo; | |
180 memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR)); | |
181 swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; | |
182 swapchainCreateInfo.surface = fSurface; | |
183 swapchainCreateInfo.minImageCount = imageCount; | |
184 swapchainCreateInfo.imageFormat = surfaceFormat; | |
185 swapchainCreateInfo.imageColorSpace = colorSpace; | |
186 swapchainCreateInfo.imageExtent = extent; | |
187 swapchainCreateInfo.imageArrayLayers = 1; | |
188 swapchainCreateInfo.imageUsage = usageFlags; | |
189 | |
190 uint32_t queueFamilies[] = { fBackendContext->fGraphicsQueueIndex, fPresentQ
ueueIndex }; | |
191 if (fBackendContext->fGraphicsQueueIndex != fPresentQueueIndex) { | |
192 swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; | |
193 swapchainCreateInfo.queueFamilyIndexCount = 2; | |
194 swapchainCreateInfo.pQueueFamilyIndices = queueFamilies; | |
195 } else { | |
196 swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; | |
197 swapchainCreateInfo.queueFamilyIndexCount = 0; | |
198 swapchainCreateInfo.pQueueFamilyIndices = nullptr; | |
199 } | |
200 | |
201 swapchainCreateInfo.preTransform = caps.currentTransform;; | |
202 swapchainCreateInfo.compositeAlpha = composite_alpha; | |
203 swapchainCreateInfo.presentMode = mode; | |
204 swapchainCreateInfo.clipped = true; | |
205 swapchainCreateInfo.oldSwapchain = fSwapchain; | |
206 | |
207 res = fCreateSwapchainKHR(fBackendContext->fDevice, &swapchainCreateInfo, nu
llptr, &fSwapchain); | |
208 if (VK_SUCCESS != res) { | |
209 return false; | |
210 } | |
211 | |
212 // destroy the old swapchain | |
213 if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) { | |
214 GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->
fDevice)); | |
215 | |
216 this->destroyBuffers(); | |
217 | |
218 fDestroySwapchainKHR(fBackendContext->fDevice, swapchainCreateInfo.oldSw
apchain, nullptr); | |
219 } | |
220 | |
221 this->createBuffers(swapchainCreateInfo.imageFormat); | |
222 | |
223 return true; | |
224 } | |
225 | |
226 void VulkanTestContext::createBuffers(VkFormat format) { | |
227 GrVkFormatToPixelConfig(format, &fPixelConfig); | |
228 | |
229 fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, n
ullptr); | |
230 SkASSERT(fImageCount); | |
231 fImages = new VkImage[fImageCount]; | |
232 fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, f
Images); | |
233 | |
234 // set up initial image layouts and create surfaces | |
235 fImageLayouts = new VkImageLayout[fImageCount]; | |
236 fSurfaces = new sk_sp<SkSurface>[fImageCount]; | |
237 for (uint32_t i = 0; i < fImageCount; ++i) { | |
238 fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED; | |
239 | |
240 GrBackendRenderTargetDesc desc; | |
241 GrVkTextureInfo info; | |
242 info.fImage = fImages[i]; | |
243 info.fAlloc = VK_NULL_HANDLE; | |
244 info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | |
245 info.fImageTiling = VK_IMAGE_TILING_OPTIMAL; | |
246 info.fFormat = format; | |
247 desc.fWidth = fWidth; | |
248 desc.fHeight = fHeight; | |
249 desc.fConfig = fPixelConfig; | |
250 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | |
251 desc.fSampleCnt = 0; | |
252 desc.fStencilBits = 0; | |
253 desc.fRenderTargetHandle = (GrBackendObject) &info; | |
254 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); | |
255 fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(fContext, desc, &p
rops); | |
256 } | |
257 | |
258 // create the command pool for the command buffers | |
259 if (VK_NULL_HANDLE == fCommandPool) { | |
260 VkCommandPoolCreateInfo commandPoolInfo; | |
261 memset(&commandPoolInfo, 0, sizeof(VkCommandPoolCreateInfo)); | |
262 commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; | |
263 // this needs to be on the render queue | |
264 commandPoolInfo.queueFamilyIndex = fBackendContext->fGraphicsQueueIndex; | |
265 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; | |
266 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
267 CreateCommandPool(fBackendContext->fDevice, &command
PoolInfo, | |
268 nullptr, &fCommandPool)); | |
269 } | |
270 | |
271 // set up the backbuffers | |
272 VkSemaphoreCreateInfo semaphoreInfo; | |
273 memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo)); | |
274 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; | |
275 semaphoreInfo.pNext = nullptr; | |
276 semaphoreInfo.flags = 0; | |
277 VkCommandBufferAllocateInfo commandBuffersInfo; | |
278 memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo)); | |
279 commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; | |
280 commandBuffersInfo.pNext = nullptr; | |
281 commandBuffersInfo.commandPool = fCommandPool; | |
282 commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; | |
283 commandBuffersInfo.commandBufferCount = 2; | |
284 VkFenceCreateInfo fenceInfo; | |
285 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo)); | |
286 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; | |
287 fenceInfo.pNext = nullptr; | |
288 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; | |
289 | |
290 // we create one additional backbuffer structure here, because we want to | |
291 // give the command buffers they contain a chance to finish before we cycle
back | |
292 fBackbuffers = new BackbufferInfo[fImageCount + 1]; | |
293 for (uint32_t i = 0; i < fImageCount + 1; ++i) { | |
294 fBackbuffers[i].fImageIndex = -1; | |
295 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
296 CreateSemaphore(fBackendContext->fDevice, &semaphore
Info, | |
297 nullptr, &fBackbuffers[i].fAcquireSe
maphore)); | |
298 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
299 CreateSemaphore(fBackendContext->fDevice, &semaphore
Info, | |
300 nullptr, &fBackbuffers[i].fRenderSem
aphore)); | |
301 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
302 AllocateCommandBuffers(fBackendContext->fDevice, &co
mmandBuffersInfo, | |
303 fBackbuffers[i].fTransitionCm
dBuffers)); | |
304 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
305 CreateFence(fBackendContext->fDevice, &fenceInfo, nu
llptr, | |
306 &fBackbuffers[i].fUsageFences[0])); | |
307 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
308 CreateFence(fBackendContext->fDevice, &fenceInfo, nu
llptr, | |
309 &fBackbuffers[i].fUsageFences[1])); | |
310 } | |
311 fCurrentBackbufferIndex = fImageCount; | |
312 } | |
313 | |
314 void VulkanTestContext::destroyBuffers() { | |
315 | |
316 if (fBackbuffers) { | |
317 for (uint32_t i = 0; i < fImageCount + 1; ++i) { | |
318 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
319 WaitForFences(fBackendContext->fDevice, 2, | |
320 fBackbuffers[i].fUsageFences, | |
321 true, UINT64_MAX)); | |
322 fBackbuffers[i].fImageIndex = -1; | |
323 GR_VK_CALL(fBackendContext->fInterface, | |
324 DestroySemaphore(fBackendContext->fDevice, | |
325 fBackbuffers[i].fAcquireSemaphore, | |
326 nullptr)); | |
327 GR_VK_CALL(fBackendContext->fInterface, | |
328 DestroySemaphore(fBackendContext->fDevice, | |
329 fBackbuffers[i].fRenderSemaphore, | |
330 nullptr)); | |
331 GR_VK_CALL(fBackendContext->fInterface, | |
332 FreeCommandBuffers(fBackendContext->fDevice, fCommandPool
, 2, | |
333 fBackbuffers[i].fTransitionCmdBuffers)
); | |
334 GR_VK_CALL(fBackendContext->fInterface, | |
335 DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fU
sageFences[0], 0)); | |
336 GR_VK_CALL(fBackendContext->fInterface, | |
337 DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fU
sageFences[1], 0)); | |
338 } | |
339 } | |
340 | |
341 delete[] fBackbuffers; | |
342 fBackbuffers = nullptr; | |
343 | |
344 delete[] fSurfaces; | |
345 fSurfaces = nullptr; | |
346 delete[] fImageLayouts; | |
347 fImageLayouts = nullptr; | |
348 delete[] fImages; | |
349 fImages = nullptr; | |
350 } | |
351 | |
352 VulkanTestContext::~VulkanTestContext() { | |
353 this->destroyContext(); | |
354 } | |
355 | |
356 void VulkanTestContext::destroyContext() { | |
357 if (!fBackendContext.get()) { | |
358 return; | |
359 } | |
360 | |
361 GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDev
ice)); | |
362 | |
363 this->destroyBuffers(); | |
364 | |
365 if (VK_NULL_HANDLE != fCommandPool) { | |
366 GR_VK_CALL(fBackendContext->fInterface, DestroyCommandPool(fBackendConte
xt->fDevice, | |
367 fCommandPool,
nullptr)); | |
368 fCommandPool = VK_NULL_HANDLE; | |
369 } | |
370 | |
371 if (VK_NULL_HANDLE != fSwapchain) { | |
372 fDestroySwapchainKHR(fBackendContext->fDevice, fSwapchain, nullptr); | |
373 fSwapchain = VK_NULL_HANDLE; | |
374 } | |
375 | |
376 if (VK_NULL_HANDLE != fSurface) { | |
377 fDestroySurfaceKHR(fBackendContext->fInstance, fSurface, nullptr); | |
378 fSurface = VK_NULL_HANDLE; | |
379 } | |
380 | |
381 delete fContext; | |
382 | |
383 fBackendContext.reset(nullptr); | |
384 } | |
385 | |
386 VulkanTestContext::BackbufferInfo* VulkanTestContext::getAvailableBackbuffer() { | |
387 SkASSERT(fBackbuffers); | |
388 | |
389 ++fCurrentBackbufferIndex; | |
390 if (fCurrentBackbufferIndex > fImageCount) { | |
391 fCurrentBackbufferIndex = 0; | |
392 } | |
393 | |
394 BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex; | |
395 | |
396 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
397 WaitForFences(fBackendContext->fDevice, 2, backbuffer->f
UsageFences, | |
398 true, UINT64_MAX)); | |
399 return backbuffer; | |
400 } | |
401 | |
402 SkSurface* VulkanTestContext::getBackbufferSurface() { | |
403 BackbufferInfo* backbuffer = this->getAvailableBackbuffer(); | |
404 SkASSERT(backbuffer); | |
405 | |
406 // reset the fence | |
407 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
408 ResetFences(fBackendContext->fDevice, 2, backbuffer->fUs
ageFences)); | |
409 // semaphores should be in unsignaled state | |
410 | |
411 // acquire the image | |
412 VkResult res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UI
NT64_MAX, | |
413 backbuffer->fAcquireSemaphore, VK_NULL_H
ANDLE, | |
414 &backbuffer->fImageIndex); | |
415 if (VK_ERROR_SURFACE_LOST_KHR == res) { | |
416 // need to figure out how to create a new vkSurface without the platform
Data* | |
417 // maybe use attach somehow? but need a Window | |
418 return nullptr; | |
419 } | |
420 if (VK_ERROR_OUT_OF_DATE_KHR == res) { | |
421 // tear swapchain down and try again | |
422 if (!this->createSwapchain(0, 0)) { | |
423 return nullptr; | |
424 } | |
425 | |
426 // acquire the image | |
427 res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64
_MAX, | |
428 backbuffer->fAcquireSemaphore, VK_NULL_HANDLE
, | |
429 &backbuffer->fImageIndex); | |
430 | |
431 if (VK_SUCCESS != res) { | |
432 return nullptr; | |
433 } | |
434 } | |
435 | |
436 // set up layout transfer from initial to color attachment | |
437 VkImageLayout layout = fImageLayouts[backbuffer->fImageIndex]; | |
438 VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ? | |
439 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT : | |
440 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPU
T_BIT; | |
441 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPU
T_BIT; | |
442 VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ? | |
443 0 : VK_ACCESS_MEMORY_READ_BIT; | |
444 VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; | |
445 | |
446 VkImageMemoryBarrier imageMemoryBarrier = { | |
447 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType | |
448 NULL, // pNext | |
449 srcAccessMask, // outputMask | |
450 dstAccessMask, // inputMask | |
451 layout, // oldLayout | |
452 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout | |
453 fPresentQueueIndex, // srcQueueFamilyIndex | |
454 fBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex | |
455 fImages[backbuffer->fImageIndex], // image | |
456 { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange | |
457 }; | |
458 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
459 ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[0],
0)); | |
460 VkCommandBufferBeginInfo info; | |
461 memset(&info, 0, sizeof(VkCommandBufferBeginInfo)); | |
462 info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | |
463 info.flags = 0; | |
464 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
465 BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[0],
&info)); | |
466 | |
467 GR_VK_CALL(fBackendContext->fInterface, | |
468 CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[0], | |
469 srcStageMask, dstStageMask, 0, | |
470 0, nullptr, | |
471 0, nullptr, | |
472 1, &imageMemoryBarrier)); | |
473 | |
474 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
475 EndCommandBuffer(backbuffer->fTransitionCmdBuffers[0]));
| |
476 | |
477 VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_
OUTPUT_BIT; | |
478 // insert the layout transfer into the queue and wait on the acquire | |
479 VkSubmitInfo submitInfo; | |
480 memset(&submitInfo, 0, sizeof(VkSubmitInfo)); | |
481 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | |
482 submitInfo.waitSemaphoreCount = 1; | |
483 submitInfo.pWaitSemaphores = &backbuffer->fAcquireSemaphore; | |
484 submitInfo.pWaitDstStageMask = &waitDstStageFlags; | |
485 submitInfo.commandBufferCount = 1; | |
486 submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[0]; | |
487 submitInfo.signalSemaphoreCount = 0; | |
488 | |
489 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
490 QueueSubmit(fBackendContext->fQueue, 1, &submitInfo, | |
491 backbuffer->fUsageFences[0])); | |
492 | |
493 return fSurfaces[backbuffer->fImageIndex].get(); | |
494 } | |
495 | |
496 | |
497 void VulkanTestContext::swapBuffers() { | |
498 | |
499 BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex; | |
500 | |
501 VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | |
502 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPU
T_BIT; | |
503 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; | |
504 VkAccessFlags srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; | |
505 VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; | |
506 | |
507 VkImageMemoryBarrier imageMemoryBarrier = { | |
508 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType | |
509 NULL, // pNext | |
510 srcAccessMask, // outputMask | |
511 dstAccessMask, // inputMask | |
512 layout, // oldLayout | |
513 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout | |
514 fBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex | |
515 fPresentQueueIndex, // dstQueueFamilyIndex | |
516 fImages[backbuffer->fImageIndex], // image | |
517 { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange | |
518 }; | |
519 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
520 ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[1],
0)); | |
521 VkCommandBufferBeginInfo info; | |
522 memset(&info, 0, sizeof(VkCommandBufferBeginInfo)); | |
523 info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | |
524 info.flags = 0; | |
525 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
526 BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[1],
&info)); | |
527 GR_VK_CALL(fBackendContext->fInterface, | |
528 CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[1], | |
529 srcStageMask, dstStageMask, 0, | |
530 0, nullptr, | |
531 0, nullptr, | |
532 1, &imageMemoryBarrier)); | |
533 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
534 EndCommandBuffer(backbuffer->fTransitionCmdBuffers[1])); | |
535 | |
536 fImageLayouts[backbuffer->fImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; | |
537 | |
538 // insert the layout transfer into the queue and wait on the acquire | |
539 VkSubmitInfo submitInfo; | |
540 memset(&submitInfo, 0, sizeof(VkSubmitInfo)); | |
541 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | |
542 submitInfo.waitSemaphoreCount = 0; | |
543 submitInfo.pWaitDstStageMask = 0; | |
544 submitInfo.commandBufferCount = 1; | |
545 submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[1]; | |
546 submitInfo.signalSemaphoreCount = 1; | |
547 submitInfo.pSignalSemaphores = &backbuffer->fRenderSemaphore; | |
548 | |
549 GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, | |
550 QueueSubmit(fBackendContext->fQueue, 1, &submitInfo, | |
551 backbuffer->fUsageFences[1])); | |
552 | |
553 // Submit present operation to present queue | |
554 const VkPresentInfoKHR presentInfo = | |
555 { | |
556 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType | |
557 NULL, // pNext | |
558 1, // waitSemaphoreCount | |
559 &backbuffer->fRenderSemaphore, // pWaitSemaphores | |
560 1, // swapchainCount | |
561 &fSwapchain, // pSwapchains | |
562 &backbuffer->fImageIndex, // pImageIndices | |
563 NULL // pResults | |
564 }; | |
565 | |
566 fQueuePresentKHR(fPresentQueue, &presentInfo); | |
567 | |
568 } | |
OLD | NEW |