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