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