1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Tests for incremental present extension
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktWsiIncrementalPresentTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkWsiPlatform.hpp"
30 #include "vkWsiUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38
39 #include "vkWsiUtil.hpp"
40
41 #include "tcuPlatform.hpp"
42 #include "tcuResultCollector.hpp"
43 #include "tcuTestLog.hpp"
44
45 #include <vector>
46 #include <string>
47
48 using std::vector;
49 using std::string;
50
51 using tcu::Maybe;
52 using tcu::UVec2;
53 using tcu::TestLog;
54
55 namespace vkt
56 {
57 namespace wsi
58 {
59 namespace
60 {
61 enum Scaling
62 {
63 SCALING_NONE,
64 SCALING_UP,
65 SCALING_DOWN
66 };
67
68 typedef vector<vk::VkExtensionProperties> Extensions;
69
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)70 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
71 {
72 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
73 requiredExtName != requiredExtensions.end();
74 ++requiredExtName)
75 {
76 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
77 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
78 }
79 }
80
createInstanceWithWsi(const vk::PlatformInterface & vkp,deUint32 version,const Extensions & supportedExtensions,vk::wsi::Type wsiType)81 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface& vkp,
82 deUint32 version,
83 const Extensions& supportedExtensions,
84 vk::wsi::Type wsiType)
85 {
86 vector<string> extensions;
87
88 extensions.push_back("VK_KHR_surface");
89 extensions.push_back(getExtensionName(wsiType));
90
91 checkAllSupported(supportedExtensions, extensions);
92
93 return vk::createDefaultInstance(vkp, version, vector<string>(), extensions);
94 }
95
getDeviceNullFeatures(void)96 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
97 {
98 vk::VkPhysicalDeviceFeatures features;
99 deMemset(&features, 0, sizeof(features));
100 return features;
101 }
102
getNumQueueFamilyIndices(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)103 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
104 {
105 deUint32 numFamilies = 0;
106
107 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
108
109 return numFamilies;
110 }
111
getSupportedQueueFamilyIndices(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)112 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
113 {
114 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
115 vector<deUint32> supportedFamilyIndices;
116
117 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
118 {
119 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
120 supportedFamilyIndices.push_back(queueFamilyNdx);
121 }
122
123 return supportedFamilyIndices;
124 }
125
chooseQueueFamilyIndex(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)126 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
127 {
128 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
129
130 if (supportedFamilyIndices.empty())
131 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
132
133 return supportedFamilyIndices[0];
134 }
135
createDeviceWithWsi(const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,bool requiresIncrementalPresent,const vk::VkAllocationCallbacks * pAllocator=DE_NULL)136 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp,
137 vk::VkInstance instance,
138 const vk::InstanceInterface& vki,
139 vk::VkPhysicalDevice physicalDevice,
140 const Extensions& supportedExtensions,
141 const deUint32 queueFamilyIndex,
142 bool requiresIncrementalPresent,
143 const vk::VkAllocationCallbacks* pAllocator = DE_NULL)
144 {
145 const float queuePriorities[] = { 1.0f };
146 const vk::VkDeviceQueueCreateInfo queueInfos[] =
147 {
148 {
149 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
150 DE_NULL,
151 (vk::VkDeviceQueueCreateFlags)0,
152 queueFamilyIndex,
153 DE_LENGTH_OF_ARRAY(queuePriorities),
154 &queuePriorities[0]
155 }
156 };
157 const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures();
158 const char* const extensions[] =
159 {
160 "VK_KHR_swapchain",
161 "VK_KHR_incremental_present"
162 };
163
164 const vk::VkDeviceCreateInfo deviceParams =
165 {
166 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
167 DE_NULL,
168 (vk::VkDeviceCreateFlags)0,
169 DE_LENGTH_OF_ARRAY(queueInfos),
170 &queueInfos[0],
171 0u,
172 DE_NULL,
173 requiresIncrementalPresent ? 2u : 1u,
174 DE_ARRAY_BEGIN(extensions),
175 &features
176 };
177
178 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
179 {
180 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
181 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
182 }
183
184 return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
185 }
186
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,vk::wsi::Type wsiType)187 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform,
188 const Extensions& supportedExtensions,
189 vk::wsi::Type wsiType)
190 {
191 try
192 {
193 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
194 }
195 catch (const tcu::NotSupportedError& e)
196 {
197 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
198 platform.hasDisplay(wsiType))
199 {
200 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
201 // must support creating native display & window for that WSI type.
202 throw tcu::TestError(e.getMessage());
203 }
204 else
205 throw;
206 }
207 }
208
createWindow(const vk::wsi::Display & display,const Maybe<UVec2> & initialSize)209 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
210 {
211 try
212 {
213 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
214 }
215 catch (const tcu::NotSupportedError& e)
216 {
217 // See createDisplay - assuming that wsi::Display was supported platform port
218 // should also support creating a window.
219 throw tcu::TestError(e.getMessage());
220 }
221 }
222
initSemaphores(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkSemaphore> & semaphores)223 void initSemaphores (const vk::DeviceInterface& vkd,
224 vk::VkDevice device,
225 std::vector<vk::VkSemaphore>& semaphores)
226 {
227 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
228 semaphores[ndx] = createSemaphore(vkd, device).disown();
229 }
230
deinitSemaphores(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkSemaphore> & semaphores)231 void deinitSemaphores (const vk::DeviceInterface& vkd,
232 vk::VkDevice device,
233 std::vector<vk::VkSemaphore>& semaphores)
234 {
235 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
236 {
237 if (semaphores[ndx] != (vk::VkSemaphore)0)
238 vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
239
240 semaphores[ndx] = (vk::VkSemaphore)0;
241 }
242
243 semaphores.clear();
244 }
245
initFences(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFence> & fences)246 void initFences (const vk::DeviceInterface& vkd,
247 vk::VkDevice device,
248 std::vector<vk::VkFence>& fences)
249 {
250 for (size_t ndx = 0; ndx < fences.size(); ndx++)
251 fences[ndx] = createFence(vkd, device).disown();
252 }
253
deinitFences(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFence> & fences)254 void deinitFences (const vk::DeviceInterface& vkd,
255 vk::VkDevice device,
256 std::vector<vk::VkFence>& fences)
257 {
258 for (size_t ndx = 0; ndx < fences.size(); ndx++)
259 {
260 if (fences[ndx] != (vk::VkFence)0)
261 vkd.destroyFence(device, fences[ndx], DE_NULL);
262
263 fences[ndx] = (vk::VkFence)0;
264 }
265
266 fences.clear();
267 }
268
getRenderFrameRect(size_t frameNdx,deUint32 imageWidth,deUint32 imageHeight)269 vk::VkRect2D getRenderFrameRect (size_t frameNdx,
270 deUint32 imageWidth,
271 deUint32 imageHeight)
272 {
273 const deUint32 x = frameNdx == 0
274 ? 0
275 : de::min(((deUint32)frameNdx) % imageWidth, imageWidth - 1u);
276 const deUint32 y = frameNdx == 0
277 ? 0
278 : de::min(((deUint32)frameNdx) % imageHeight, imageHeight - 1u);
279 const deUint32 width = frameNdx == 0
280 ? imageWidth
281 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageWidth / 3), imageWidth - x);
282 const deUint32 height = frameNdx == 0
283 ? imageHeight
284 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageHeight / 3), imageHeight - y);
285 const vk::VkRect2D rect =
286 {
287 { (deInt32)x, (deInt32)y },
288 { width, height }
289 };
290
291 DE_ASSERT(width > 0);
292 DE_ASSERT(height > 0);
293
294 return rect;
295 }
296
getUpdatedRects(size_t firstFrameNdx,size_t lastFrameNdx,deUint32 width,deUint32 height)297 vector<vk::VkRectLayerKHR> getUpdatedRects (size_t firstFrameNdx,
298 size_t lastFrameNdx,
299 deUint32 width,
300 deUint32 height)
301 {
302 vector<vk::VkRectLayerKHR> rects;
303
304 for (size_t frameNdx = firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++)
305 {
306 const vk::VkRect2D rect = getRenderFrameRect(frameNdx, width, height);
307 const vk::VkRectLayerKHR rectLayer =
308 {
309 rect.offset,
310 rect.extent,
311 0
312 };
313
314 rects.push_back(rectLayer);
315 }
316
317 return rects;
318 }
319
cmdRenderFrame(const vk::DeviceInterface & vkd,vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout,vk::VkPipeline pipeline,size_t frameNdx,deUint32 imageWidth,deUint32 imageHeight)320 void cmdRenderFrame (const vk::DeviceInterface& vkd,
321 vk::VkCommandBuffer commandBuffer,
322 vk::VkPipelineLayout pipelineLayout,
323 vk::VkPipeline pipeline,
324 size_t frameNdx,
325 deUint32 imageWidth,
326 deUint32 imageHeight)
327 {
328 const deUint32 mask = (deUint32)frameNdx;
329
330 if (frameNdx == 0)
331 {
332 const vk::VkRect2D scissor = vk::makeRect2D(imageWidth, imageHeight);
333 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
334 const vk::VkClearAttachment attachment =
335 {
336 vk::VK_IMAGE_ASPECT_COLOR_BIT,
337 0u,
338 vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f)
339 };
340 const vk::VkClearRect rect =
341 {
342 scissor,
343 0u,
344 1u
345 };
346
347 vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
348 }
349
350 {
351 const vk::VkRect2D scissor = getRenderFrameRect(frameNdx, imageWidth, imageHeight);
352 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
353
354 vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &mask);
355 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
356 vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
357 }
358 }
359
createCommandBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool commandPool,vk::VkPipelineLayout pipelineLayout,vk::VkRenderPass renderPass,vk::VkFramebuffer framebuffer,vk::VkPipeline pipeline,vk::VkImage image,bool isFirst,size_t imageNextFrame,size_t currentFrame,deUint32 imageWidth,deUint32 imageHeight)360 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
361 vk::VkDevice device,
362 vk::VkCommandPool commandPool,
363 vk::VkPipelineLayout pipelineLayout,
364 vk::VkRenderPass renderPass,
365 vk::VkFramebuffer framebuffer,
366 vk::VkPipeline pipeline,
367 vk::VkImage image,
368 bool isFirst,
369 size_t imageNextFrame,
370 size_t currentFrame,
371 deUint32 imageWidth,
372 deUint32 imageHeight)
373 {
374 const vk::VkCommandBufferAllocateInfo allocateInfo =
375 {
376 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
377 DE_NULL,
378
379 commandPool,
380 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
381 1
382 };
383
384 vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo));
385 beginCommandBuffer(vkd, *commandBuffer, 0u);
386
387 {
388 const vk::VkImageSubresourceRange subRange =
389 {
390 vk::VK_IMAGE_ASPECT_COLOR_BIT,
391 0,
392 1,
393 0,
394 1
395 };
396 const vk::VkImageMemoryBarrier barrier =
397 {
398 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
399 DE_NULL,
400 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
401 vk::VK_ACCESS_TRANSFER_READ_BIT | vk::VK_ACCESS_TRANSFER_WRITE_BIT,
402 isFirst ? vk::VK_IMAGE_LAYOUT_UNDEFINED : vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
403 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
404 VK_QUEUE_FAMILY_IGNORED,
405 VK_QUEUE_FAMILY_IGNORED,
406 image,
407 subRange
408 };
409 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &barrier);
410 }
411
412 beginRenderPass(vkd, *commandBuffer, renderPass, framebuffer, vk::makeRect2D(imageWidth, imageHeight), tcu::Vec4(0.25f, 0.5f, 0.75f, 1.0f));
413
414 for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++)
415 cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight);
416
417 endRenderPass(vkd, *commandBuffer);
418
419 endCommandBuffer(vkd, *commandBuffer);
420 return commandBuffer;
421 }
422
deinitCommandBuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool commandPool,std::vector<vk::VkCommandBuffer> & commandBuffers)423 void deinitCommandBuffers (const vk::DeviceInterface& vkd,
424 vk::VkDevice device,
425 vk::VkCommandPool commandPool,
426 std::vector<vk::VkCommandBuffer>& commandBuffers)
427 {
428 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
429 {
430 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
431 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
432
433 commandBuffers[ndx] = (vk::VkCommandBuffer)0;
434 }
435
436 commandBuffers.clear();
437 }
438
createCommandPool(const vk::DeviceInterface & vkd,vk::VkDevice device,deUint32 queueFamilyIndex)439 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
440 vk::VkDevice device,
441 deUint32 queueFamilyIndex)
442 {
443 const vk::VkCommandPoolCreateInfo createInfo =
444 {
445 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
446 DE_NULL,
447 0u,
448 queueFamilyIndex
449 };
450
451 return vk::createCommandPool(vkd, device, &createInfo);
452 }
453
createFramebuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,vk::VkImageView imageView,deUint32 width,deUint32 height)454 vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd,
455 vk::VkDevice device,
456 vk::VkRenderPass renderPass,
457 vk::VkImageView imageView,
458 deUint32 width,
459 deUint32 height)
460 {
461 const vk::VkFramebufferCreateInfo createInfo =
462 {
463 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
464 DE_NULL,
465
466 0u,
467 renderPass,
468 1u,
469 &imageView,
470 width,
471 height,
472 1u
473 };
474
475 return vk::createFramebuffer(vkd, device, &createInfo);
476 }
477
initFramebuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,std::vector<vk::VkImageView> imageViews,deUint32 width,deUint32 height,std::vector<vk::VkFramebuffer> & framebuffers)478 void initFramebuffers (const vk::DeviceInterface& vkd,
479 vk::VkDevice device,
480 vk::VkRenderPass renderPass,
481 std::vector<vk::VkImageView> imageViews,
482 deUint32 width,
483 deUint32 height,
484 std::vector<vk::VkFramebuffer>& framebuffers)
485 {
486 DE_ASSERT(framebuffers.size() == imageViews.size());
487
488 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
489 framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
490 }
491
deinitFramebuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFramebuffer> & framebuffers)492 void deinitFramebuffers (const vk::DeviceInterface& vkd,
493 vk::VkDevice device,
494 std::vector<vk::VkFramebuffer>& framebuffers)
495 {
496 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
497 {
498 if (framebuffers[ndx] != (vk::VkFramebuffer)0)
499 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
500
501 framebuffers[ndx] = (vk::VkFramebuffer)0;
502 }
503
504 framebuffers.clear();
505 }
506
createImageView(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkFormat format)507 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
508 vk::VkDevice device,
509 vk::VkImage image,
510 vk::VkFormat format)
511 {
512 const vk::VkImageViewCreateInfo createInfo =
513 {
514 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
515 DE_NULL,
516
517 0u,
518 image,
519 vk::VK_IMAGE_VIEW_TYPE_2D,
520 format,
521 vk::makeComponentMappingRGBA(),
522 {
523 vk::VK_IMAGE_ASPECT_COLOR_BIT,
524 0u,
525 1u,
526 0u,
527 1u
528 }
529 };
530
531 return vk::createImageView(vkd, device, &createInfo, DE_NULL);
532 }
533
initImageViews(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<vk::VkImage> & images,vk::VkFormat format,std::vector<vk::VkImageView> & imageViews)534 void initImageViews (const vk::DeviceInterface& vkd,
535 vk::VkDevice device,
536 const std::vector<vk::VkImage>& images,
537 vk::VkFormat format,
538 std::vector<vk::VkImageView>& imageViews)
539 {
540 DE_ASSERT(images.size() == imageViews.size());
541
542 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
543 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
544 }
545
deinitImageViews(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkImageView> & imageViews)546 void deinitImageViews (const vk::DeviceInterface& vkd,
547 vk::VkDevice device,
548 std::vector<vk::VkImageView>& imageViews)
549 {
550 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
551 {
552 if (imageViews[ndx] != (vk::VkImageView)0)
553 vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
554
555 imageViews[ndx] = (vk::VkImageView)0;
556 }
557
558 imageViews.clear();
559 }
560
createRenderPass(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format)561 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd,
562 vk::VkDevice device,
563 vk::VkFormat format)
564 {
565 return vk::makeRenderPass(vkd, device, format, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_LOAD, vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
566 }
567
createPipeline(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,vk::VkPipelineLayout layout,vk::VkShaderModule vertexShaderModule,vk::VkShaderModule fragmentShaderModule,deUint32 width,deUint32 height)568 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd,
569 vk::VkDevice device,
570 vk::VkRenderPass renderPass,
571 vk::VkPipelineLayout layout,
572 vk::VkShaderModule vertexShaderModule,
573 vk::VkShaderModule fragmentShaderModule,
574 deUint32 width,
575 deUint32 height)
576 {
577 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
578 {
579 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
580 DE_NULL,
581 0u,
582 0u,
583 DE_NULL,
584 0u,
585 DE_NULL
586 };
587 const std::vector<vk::VkViewport> viewports (1, vk::makeViewport(tcu::UVec2(width, height)));
588 const std::vector<vk::VkRect2D> noScissors;
589
590 return vk::makeGraphicsPipeline(vkd, // const DeviceInterface& vk
591 device, // const VkDevice device
592 layout, // const VkPipelineLayout pipelineLayout
593 vertexShaderModule, // const VkShaderModule vertexShaderModule
594 DE_NULL, // const VkShaderModule tessellationControlShaderModule
595 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
596 DE_NULL, // const VkShaderModule geometryShaderModule
597 fragmentShaderModule, // const VkShaderModule fragmentShaderModule
598 renderPass, // const VkRenderPass renderPass
599 viewports, // const std::vector<VkViewport>& viewports
600 noScissors, // const std::vector<VkRect2D>& scissors
601 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
602 0u, // const deUint32 subpass
603 0u, // const deUint32 patchControlPoints
604 &vertexInputState); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
605 }
606
createPipelineLayout(const vk::DeviceInterface & vkd,vk::VkDevice device)607 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd,
608 vk::VkDevice device)
609 {
610 const vk::VkPushConstantRange pushConstants[] =
611 {
612 {
613 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
614 0u,
615 4u
616 }
617 };
618 const vk::VkPipelineLayoutCreateInfo createInfo =
619 {
620 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
621 DE_NULL,
622 0u,
623
624 0u,
625 DE_NULL,
626
627 DE_LENGTH_OF_ARRAY(pushConstants),
628 pushConstants
629 };
630
631 return vk::createPipelineLayout(vkd, device, &createInfo);
632 }
633
634 struct TestConfig
635 {
636 vk::wsi::Type wsiType;
637 Scaling scaling;
638 bool useIncrementalPresent;
639 vk::VkPresentModeKHR presentMode;
640 vk::VkSurfaceTransformFlagsKHR transform;
641 vk::VkCompositeAlphaFlagsKHR alpha;
642 };
643
644 class IncrementalPresentTestInstance : public TestInstance
645 {
646 public:
647 IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig);
648 ~IncrementalPresentTestInstance (void);
649
650 tcu::TestStatus iterate (void);
651
652 private:
653 const TestConfig m_testConfig;
654 const bool m_useIncrementalPresent;
655 const vk::PlatformInterface& m_vkp;
656 const Extensions m_instanceExtensions;
657 const vk::Unique<vk::VkInstance> m_instance;
658 const vk::InstanceDriver m_vki;
659 const vk::VkPhysicalDevice m_physicalDevice;
660 const de::UniquePtr<vk::wsi::Display> m_nativeDisplay;
661 const de::UniquePtr<vk::wsi::Window> m_nativeWindow;
662 const vk::Unique<vk::VkSurfaceKHR> m_surface;
663
664 const deUint32 m_queueFamilyIndex;
665 const Extensions m_deviceExtensions;
666 const vk::Unique<vk::VkDevice> m_device;
667 const vk::DeviceDriver m_vkd;
668 const vk::VkQueue m_queue;
669
670 const vk::Unique<vk::VkCommandPool> m_commandPool;
671 const vk::Unique<vk::VkShaderModule> m_vertexShaderModule;
672 const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule;
673 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
674
675 const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties;
676 const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats;
677 const vector<vk::VkPresentModeKHR> m_presentModes;
678
679 tcu::ResultCollector m_resultCollector;
680
681 vk::Move<vk::VkSwapchainKHR> m_swapchain;
682 std::vector<vk::VkImage> m_swapchainImages;
683 std::vector<size_t> m_imageNextFrames;
684 std::vector<bool> m_isFirst;
685
686 vk::Move<vk::VkRenderPass> m_renderPass;
687 vk::Move<vk::VkPipeline> m_pipeline;
688
689 std::vector<vk::VkImageView> m_swapchainImageViews;
690 std::vector<vk::VkFramebuffer> m_framebuffers;
691 std::vector<vk::VkCommandBuffer> m_commandBuffers;
692 std::vector<vk::VkSemaphore> m_acquireSemaphores;
693 std::vector<vk::VkSemaphore> m_renderSemaphores;
694 std::vector<vk::VkFence> m_fences;
695
696 vk::VkSemaphore m_freeAcquireSemaphore;
697 vk::VkSemaphore m_freeRenderSemaphore;
698
699 std::vector<vk::VkSwapchainCreateInfoKHR> m_swapchainConfigs;
700 size_t m_swapchainConfigNdx;
701
702 const size_t m_frameCount;
703 size_t m_frameNdx;
704
705 const size_t m_maxOutOfDateCount;
706 size_t m_outOfDateCount;
707
708 void initSwapchainResources (void);
709 void deinitSwapchainResources (void);
710 void render (void);
711 };
712
generateSwapchainConfigs(vk::VkSurfaceKHR surface,const deUint32 * queueFamilyIndex,Scaling scaling,const vk::VkSurfaceCapabilitiesKHR & properties,const vector<vk::VkSurfaceFormatKHR> & formats,const vector<vk::VkPresentModeKHR> & presentModes,vk::VkPresentModeKHR presentMode,const vk::VkSurfaceTransformFlagsKHR transform,const vk::VkCompositeAlphaFlagsKHR alpha)713 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR surface,
714 const deUint32 *queueFamilyIndex,
715 Scaling scaling,
716 const vk::VkSurfaceCapabilitiesKHR& properties,
717 const vector<vk::VkSurfaceFormatKHR>& formats,
718 const vector<vk::VkPresentModeKHR>& presentModes,
719 vk::VkPresentModeKHR presentMode,
720 const vk::VkSurfaceTransformFlagsKHR transform,
721 const vk::VkCompositeAlphaFlagsKHR alpha)
722 {
723 const deUint32 imageLayers = 1u;
724 const vk::VkImageUsageFlags imageUsage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
725 const vk::VkBool32 clipped = VK_FALSE;
726 vector<vk::VkSwapchainCreateInfoKHR> createInfos;
727
728 const deUint32 currentWidth = properties.currentExtent.width != 0xFFFFFFFFu
729 ? properties.currentExtent.width
730 : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
731 const deUint32 currentHeight = properties.currentExtent.height != 0xFFFFFFFFu
732 ? properties.currentExtent.height
733 : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
734
735 const deUint32 imageWidth = scaling == SCALING_NONE
736 ? currentWidth
737 : (scaling == SCALING_UP
738 ? de::max(31u, properties.minImageExtent.width)
739 : de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentWidth+1), properties.maxImageExtent.width));
740 const deUint32 imageHeight = scaling == SCALING_NONE
741 ? currentHeight
742 : (scaling == SCALING_UP
743 ? de::max(31u, properties.minImageExtent.height)
744 : de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentHeight+1), properties.maxImageExtent.height));
745 const vk::VkExtent2D imageSize = { imageWidth, imageHeight };
746 const vk::VkExtent2D dummySize = { de::max(31u, properties.minImageExtent.width), de::max(31u, properties.minImageExtent.height) };
747
748 {
749 size_t presentModeNdx;
750
751 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
752 {
753 if (presentModes[presentModeNdx] == presentMode)
754 break;
755 }
756
757 if (presentModeNdx == presentModes.size())
758 TCU_THROW(NotSupportedError, "Present mode not supported");
759
760 if ((properties.supportedTransforms & transform) == 0)
761 TCU_THROW(NotSupportedError, "Transform not supported");
762
763 if ((properties.supportedCompositeAlpha & alpha) == 0)
764 TCU_THROW(NotSupportedError, "Composite alpha not supported");
765 }
766
767 for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
768 {
769
770 const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
771 const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
772 const vk::VkFormat imageFormat = formats[formatNdx].format;
773 const vk::VkColorSpaceKHR imageColorSpace = formats[formatNdx].colorSpace;
774 const vk::VkSwapchainCreateInfoKHR createInfo =
775 {
776 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
777 DE_NULL,
778 0u,
779 surface,
780 properties.minImageCount,
781 imageFormat,
782 imageColorSpace,
783 imageSize,
784 imageLayers,
785 imageUsage,
786 vk::VK_SHARING_MODE_EXCLUSIVE,
787 1u,
788 queueFamilyIndex,
789 preTransform,
790 compositeAlpha,
791 presentMode,
792 clipped,
793 (vk::VkSwapchainKHR)0
794 };
795
796 createInfos.push_back(createInfo);
797
798 // add an extra dummy swapchain
799 const vk::VkSwapchainCreateInfoKHR dummyInfo =
800 {
801 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
802 DE_NULL,
803 0u,
804 surface,
805 properties.minImageCount,
806 imageFormat,
807 imageColorSpace,
808 dummySize,
809 imageLayers,
810 imageUsage,
811 vk::VK_SHARING_MODE_EXCLUSIVE,
812 1u,
813 queueFamilyIndex,
814 preTransform,
815 compositeAlpha,
816 presentMode,
817 clipped,
818 (vk::VkSwapchainKHR)0
819 };
820
821 createInfos.push_back(dummyInfo);
822 }
823
824 return createInfos;
825 }
826
IncrementalPresentTestInstance(Context & context,const TestConfig & testConfig)827 IncrementalPresentTestInstance::IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig)
828 : TestInstance (context)
829 , m_testConfig (testConfig)
830 , m_useIncrementalPresent (testConfig.useIncrementalPresent)
831 , m_vkp (context.getPlatformInterface())
832 , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
833 , m_instance (createInstanceWithWsi(m_vkp, context.getUsedApiVersion(), m_instanceExtensions, testConfig.wsiType))
834 , m_vki (m_vkp, *m_instance)
835 , m_physicalDevice (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
836 , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
837 , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
838 , m_surface (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
839
840 , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
841 , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
842 , m_device (createDeviceWithWsi(m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useIncrementalPresent))
843 , m_vkd (m_vkp, *m_instance, *m_device)
844 , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
845
846 , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
847 , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
848 , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
849 , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device))
850
851 , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
852 , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
853 , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
854
855 , m_freeAcquireSemaphore ((vk::VkSemaphore)0)
856 , m_freeRenderSemaphore ((vk::VkSemaphore)0)
857
858 , m_swapchainConfigs (generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode, testConfig.transform, testConfig.alpha))
859 , m_swapchainConfigNdx (0u)
860
861 , m_frameCount (60u * 5u)
862 , m_frameNdx (0u)
863
864 , m_maxOutOfDateCount (20u)
865 , m_outOfDateCount (0u)
866 {
867 {
868 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
869 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
870 }
871 }
872
~IncrementalPresentTestInstance(void)873 IncrementalPresentTestInstance::~IncrementalPresentTestInstance (void)
874 {
875 deinitSwapchainResources();
876 }
877
initSwapchainResources(void)878 void IncrementalPresentTestInstance::initSwapchainResources (void)
879 {
880 const size_t fenceCount = 6;
881 const deUint32 imageWidth = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
882 const deUint32 imageHeight = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
883 const vk::VkFormat imageFormat = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
884
885 m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
886 m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
887
888 m_imageNextFrames.resize(m_swapchainImages.size(), 0);
889 m_isFirst.resize(m_swapchainImages.size(), true);
890
891 m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat);
892 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
893
894 m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
895 m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
896 m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
897 m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
898
899 m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
900 m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
901
902 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
903 m_freeRenderSemaphore = (vk::VkSemaphore)0;
904
905 m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown();
906 m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown();
907
908 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
909 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
910 initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
911 initSemaphores(m_vkd, *m_device, m_renderSemaphores);
912
913 initFences(m_vkd, *m_device, m_fences);
914 }
915
deinitSwapchainResources(void)916 void IncrementalPresentTestInstance::deinitSwapchainResources (void)
917 {
918 VK_CHECK(m_vkd.queueWaitIdle(m_queue));
919
920 if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
921 {
922 m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
923 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
924 }
925
926 if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
927 {
928 m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
929 m_freeRenderSemaphore = (vk::VkSemaphore)0;
930 }
931
932 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
933 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
934 deinitFences(m_vkd, *m_device, m_fences);
935 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
936 deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
937 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
938
939 m_swapchainImages.clear();
940 m_imageNextFrames.clear();
941 m_isFirst.clear();
942
943 m_swapchain = vk::Move<vk::VkSwapchainKHR>();
944 m_renderPass = vk::Move<vk::VkRenderPass>();
945 m_pipeline = vk::Move<vk::VkPipeline>();
946
947 }
948
render(void)949 void IncrementalPresentTestInstance::render (void)
950 {
951 const deUint64 foreverNs = 0xFFFFFFFFFFFFFFFFul;
952 const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()];
953 const deUint32 width = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
954 const deUint32 height = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
955 size_t imageNextFrame;
956
957 // Throttle execution
958 if (m_frameNdx >= m_fences.size())
959 {
960 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
961 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
962
963 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
964 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
965 }
966
967 vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore;
968 vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore;
969 deUint32 imageIndex;
970
971 // Acquire next image
972 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0, &imageIndex));
973
974 // Create command buffer
975 {
976 imageNextFrame = m_imageNextFrames[imageIndex];
977 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, m_framebuffers[imageIndex], *m_pipeline, m_swapchainImages[imageIndex], m_isFirst[imageIndex], imageNextFrame, m_frameNdx, width, height).disown();
978 m_imageNextFrames[imageIndex] = m_frameNdx + 1;
979 m_isFirst[imageIndex] = false;
980 }
981
982 // Submit command buffer
983 {
984 const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
985 const vk::VkSubmitInfo submitInfo =
986 {
987 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
988 DE_NULL,
989 1u,
990 ¤tAcquireSemaphore,
991 &dstStageMask,
992 1u,
993 &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
994 1u,
995 ¤tRenderSemaphore
996 };
997
998 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
999 }
1000
1001 // Present frame
1002 if (m_useIncrementalPresent)
1003 {
1004 vk::VkResult result;
1005 const vector<vk::VkRectLayerKHR> rects = getUpdatedRects(imageNextFrame, m_frameNdx, width, height);
1006 const vk::VkPresentRegionKHR region =
1007 {
1008 (deUint32)rects.size(),
1009 rects.empty() ? DE_NULL : &rects[0]
1010 };
1011 const vk::VkPresentRegionsKHR regionInfo =
1012 {
1013 vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
1014 DE_NULL,
1015 1u,
1016 ®ion
1017 };
1018 const vk::VkPresentInfoKHR presentInfo =
1019 {
1020 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1021 ®ionInfo,
1022 1u,
1023 ¤tRenderSemaphore,
1024 1u,
1025 &*m_swapchain,
1026 &imageIndex,
1027 &result
1028 };
1029
1030 VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1031 VK_CHECK_WSI(result);
1032 }
1033 else
1034 {
1035 vk::VkResult result;
1036 const vk::VkPresentInfoKHR presentInfo =
1037 {
1038 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1039 DE_NULL,
1040 1u,
1041 ¤tRenderSemaphore,
1042 1u,
1043 &*m_swapchain,
1044 &imageIndex,
1045 &result
1046 };
1047
1048 VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1049 VK_CHECK_WSI(result);
1050 }
1051
1052 {
1053 m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex];
1054 m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
1055
1056 m_freeRenderSemaphore = m_renderSemaphores[imageIndex];
1057 m_renderSemaphores[imageIndex] = currentRenderSemaphore;
1058 }
1059 }
1060
iterate(void)1061 tcu::TestStatus IncrementalPresentTestInstance::iterate (void)
1062 {
1063 // Initialize swapchain specific resources
1064 // Render test
1065 try
1066 {
1067 if (m_frameNdx == 0)
1068 {
1069 if (m_outOfDateCount == 0)
1070 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage;
1071
1072 initSwapchainResources();
1073 }
1074
1075 render();
1076 }
1077 catch (const vk::Error& error)
1078 {
1079 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1080 {
1081 m_swapchainConfigs = generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode, m_testConfig.transform, m_testConfig.alpha);
1082
1083 if (m_outOfDateCount < m_maxOutOfDateCount)
1084 {
1085 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1086 deinitSwapchainResources();
1087 m_frameNdx = 0;
1088 m_outOfDateCount++;
1089
1090 return tcu::TestStatus::incomplete();
1091 }
1092 else
1093 {
1094 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1095 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1096 }
1097 }
1098 else
1099 {
1100 m_resultCollector.fail(error.what());
1101 }
1102
1103 deinitSwapchainResources();
1104
1105 m_swapchainConfigNdx++;
1106 m_frameNdx = 0;
1107 m_outOfDateCount = 0;
1108
1109 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1110 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1111 else
1112 return tcu::TestStatus::incomplete();
1113 }
1114
1115 m_frameNdx++;
1116
1117 if (m_frameNdx >= m_frameCount)
1118 {
1119 m_frameNdx = 0;
1120 m_outOfDateCount = 0;
1121 m_swapchainConfigNdx++;
1122
1123 deinitSwapchainResources();
1124
1125 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1126 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1127 else
1128 return tcu::TestStatus::incomplete();
1129 }
1130 else
1131 return tcu::TestStatus::incomplete();
1132 }
1133
1134 struct Programs
1135 {
initvkt::wsi::__anoncbc7440f0111::Programs1136 static void init (vk::SourceCollections& dst, TestConfig)
1137 {
1138 dst.glslSources.add("quad-vert") << glu::VertexSource(
1139 "#version 450\n"
1140 "out gl_PerVertex {\n"
1141 "\tvec4 gl_Position;\n"
1142 "};\n"
1143 "highp float;\n"
1144 "void main (void) {\n"
1145 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1146 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1147 "}\n");
1148 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1149 "#version 310 es\n"
1150 "layout(location = 0) out highp vec4 o_color;\n"
1151 "layout(push_constant) uniform PushConstant {\n"
1152 "\thighp uint mask;\n"
1153 "} pushConstants;\n"
1154 "void main (void)\n"
1155 "{\n"
1156 "\thighp uint mask = pushConstants.mask;\n"
1157 "\thighp uint x = mask ^ uint(gl_FragCoord.x);\n"
1158 "\thighp uint y = mask ^ uint(gl_FragCoord.y);\n"
1159 "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1160 "\t + 64u * bitfieldExtract(y, 1, 1)\n"
1161 "\t + 32u * bitfieldExtract(x, 3, 1);\n"
1162 "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1163 "\t + 64u * bitfieldExtract(x, 2, 1)\n"
1164 "\t + 32u * bitfieldExtract(y, 3, 1);\n"
1165 "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1166 "\t + 64u * bitfieldExtract(y, 2, 1)\n"
1167 "\t + 32u * bitfieldExtract(x, 4, 1);\n"
1168 "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1169 "}\n");
1170 }
1171 };
1172
1173 } // anonymous
1174
createIncrementalPresentTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1175 void createIncrementalPresentTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1176 {
1177 const struct
1178 {
1179 Scaling scaling;
1180 const char* name;
1181 } scaling [] =
1182 {
1183 { SCALING_NONE, "scale_none" },
1184 { SCALING_UP, "scale_up" },
1185 { SCALING_DOWN, "scale_down" }
1186 };
1187 const struct
1188 {
1189 vk::VkPresentModeKHR mode;
1190 const char* name;
1191 } presentModes[] =
1192 {
1193 { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" },
1194 { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" },
1195 { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" },
1196 { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" }
1197 };
1198 const struct
1199 {
1200 vk::VkSurfaceTransformFlagsKHR transform;
1201 const char* name;
1202 } transforms[] =
1203 {
1204 { vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, "identity" },
1205 { vk::VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, "rotate_90" },
1206 { vk::VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, "rotate_180" },
1207 { vk::VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, "rotate_270" },
1208 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, "horizontal_mirror" },
1209 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, "horizontal_mirror_rotate_90" },
1210 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, "horizontal_mirror_rotate_180" },
1211 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, "horizontal_mirror_rotate_270" },
1212 { vk::VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR, "inherit" }
1213 };
1214 const struct
1215 {
1216 vk::VkCompositeAlphaFlagsKHR alpha;
1217 const char* name;
1218 } alphas[] =
1219 {
1220 { vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, "opaque" },
1221 { vk::VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, "pre_multiplied" },
1222 { vk::VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, "post_multiplied" },
1223 { vk::VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, "inherit" }
1224 };
1225
1226 for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
1227 {
1228 if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND)
1229 continue;
1230
1231 if (scaling[scalingNdx].scaling != SCALING_NONE && vk::wsi::getPlatformProperties(wsiType).swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
1232 continue;
1233
1234 {
1235
1236 de::MovePtr<tcu::TestCaseGroup> scaleGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name));
1237
1238 for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1239 {
1240 de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name));
1241
1242 for (size_t transformNdx = 0; transformNdx < DE_LENGTH_OF_ARRAY(transforms); transformNdx++)
1243 {
1244 de::MovePtr<tcu::TestCaseGroup> transformGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), transforms[transformNdx].name, transforms[transformNdx].name));
1245
1246 for (size_t alphaNdx = 0; alphaNdx < DE_LENGTH_OF_ARRAY(alphas); alphaNdx++)
1247 {
1248 de::MovePtr<tcu::TestCaseGroup> alphaGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), alphas[alphaNdx].name, alphas[alphaNdx].name));
1249
1250 for (size_t ref = 0; ref < 2; ref++)
1251 {
1252 const bool isReference = (ref == 0);
1253 const char* const name = isReference ? "reference" : "incremental_present";
1254 TestConfig config;
1255
1256 config.wsiType = wsiType;
1257 config.scaling = scaling[scalingNdx].scaling;
1258 config.useIncrementalPresent = !isReference;
1259 config.presentMode = presentModes[presentModeNdx].mode;
1260 config.transform = transforms[transformNdx].transform;
1261 config.alpha = alphas[alphaNdx].alpha;
1262
1263 alphaGroup->addChild(new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1264 }
1265
1266 transformGroup->addChild(alphaGroup.release());
1267 }
1268
1269 presentModeGroup->addChild(transformGroup.release());
1270 }
1271
1272 scaleGroup->addChild(presentModeGroup.release());
1273 }
1274
1275 testGroup->addChild(scaleGroup.release());
1276 }
1277 }
1278 }
1279
1280 } // wsi
1281 } // vkt
1282