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