Improve GLSL source program support
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / wsi / vktWsiSharedPresentableImageTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 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 shared presentable image extension
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktWsiSharedPresentableImageTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkWsiPlatform.hpp"
30 #include "vkWsiUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkPrograms.hpp"
36
37 #include "vkWsiUtil.hpp"
38
39 #include "tcuPlatform.hpp"
40 #include "tcuResultCollector.hpp"
41 #include "tcuTestLog.hpp"
42
43 #include <vector>
44 #include <string>
45
46 using std::vector;
47 using std::string;
48
49 using tcu::Maybe;
50 using tcu::UVec2;
51 using tcu::TestLog;
52
53 namespace vkt
54 {
55 namespace wsi
56 {
57 namespace
58 {
59 enum Scaling
60 {
61         SCALING_NONE,
62         SCALING_UP,
63         SCALING_DOWN
64 };
65
66 typedef vector<vk::VkExtensionProperties> Extensions;
67
68 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
69 {
70         for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
71                  requiredExtName != requiredExtensions.end();
72                  ++requiredExtName)
73         {
74                 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
75                         TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
76         }
77 }
78
79 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface&            vkp,
80                                                                                                 const Extensions&                                       supportedExtensions,
81                                                                                                 vk::wsi::Type                                           wsiType)
82 {
83         vector<string>  extensions;
84
85         extensions.push_back("VK_KHR_surface");
86         extensions.push_back("VK_KHR_get_surface_capabilities2");
87         // Required for device extension to expose new physical device bits (in this
88         // case, presentation mode enums)
89         extensions.push_back("VK_KHR_get_physical_device_properties2");
90         extensions.push_back(getExtensionName(wsiType));
91
92         checkAllSupported(supportedExtensions, extensions);
93
94         return vk::createDefaultInstance(vkp, vector<string>(), extensions);
95 }
96
97 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
98 {
99         vk::VkPhysicalDeviceFeatures features;
100         deMemset(&features, 0, sizeof(features));
101         return features;
102 }
103
104 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
105 {
106         deUint32        numFamilies             = 0;
107
108         vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
109
110         return numFamilies;
111 }
112
113 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
114 {
115         const deUint32          numTotalFamilyIndices   = getNumQueueFamilyIndices(vki, physicalDevice);
116         vector<deUint32>        supportedFamilyIndices;
117
118         for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
119         {
120                 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
121                         supportedFamilyIndices.push_back(queueFamilyNdx);
122         }
123
124         return supportedFamilyIndices;
125 }
126
127 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
128 {
129         const vector<deUint32>  supportedFamilyIndices  = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
130
131         if (supportedFamilyIndices.empty())
132                 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
133
134         return supportedFamilyIndices[0];
135 }
136
137 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::InstanceInterface&                vki,
138                                                                                         vk::VkPhysicalDevice                            physicalDevice,
139                                                                                         const Extensions&                                       supportedExtensions,
140                                                                                         const deUint32                                          queueFamilyIndex,
141                                                                                         bool                                                            requiresSharedPresentableImage,
142                                                                                         const vk::VkAllocationCallbacks*        pAllocator = DE_NULL)
143 {
144         const float                                                     queuePriorities[]       = { 1.0f };
145         const vk::VkDeviceQueueCreateInfo       queueInfos[]            =
146         {
147                 {
148                         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
149                         DE_NULL,
150                         (vk::VkDeviceQueueCreateFlags)0,
151                         queueFamilyIndex,
152                         DE_LENGTH_OF_ARRAY(queuePriorities),
153                         &queuePriorities[0]
154                 }
155         };
156         const vk::VkPhysicalDeviceFeatures      features                = getDeviceNullFeatures();
157         const char* const                                       extensions[]    =
158         {
159                 "VK_KHR_swapchain",
160                 "VK_KHR_shared_presentable_image"
161         };
162
163         const vk::VkDeviceCreateInfo            deviceParams    =
164         {
165                 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
166                 DE_NULL,
167                 (vk::VkDeviceCreateFlags)0,
168                 DE_LENGTH_OF_ARRAY(queueInfos),
169                 &queueInfos[0],
170                 0u,
171                 DE_NULL,
172                 requiresSharedPresentableImage ? 2u : 1u,
173                 DE_ARRAY_BEGIN(extensions),
174                 &features
175         };
176
177         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
178         {
179                 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
180                         TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
181         }
182
183         return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
184 }
185
186 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform&        platform,
187                                                                                          const Extensions&              supportedExtensions,
188                                                                                          vk::wsi::Type                  wsiType)
189 {
190         try
191         {
192                 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
193         }
194         catch (const tcu::NotSupportedError& e)
195         {
196                 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
197                 {
198                         // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
199                         // must support creating native display & window for that WSI type.
200                         throw tcu::TestError(e.getMessage());
201                 }
202                 else
203                         throw;
204         }
205 }
206
207 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
208 {
209         try
210         {
211                 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
212         }
213         catch (const tcu::NotSupportedError& e)
214         {
215                 // See createDisplay - assuming that wsi::Display was supported platform port
216                 // should also support creating a window.
217                 throw tcu::TestError(e.getMessage());
218         }
219 }
220
221 bool wsiTypeSupportsScaling (vk::wsi::Type wsiType)
222 {
223         return vk::wsi::getPlatformProperties(wsiType).swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE;
224 }
225
226 void initSemaphores (const vk::DeviceInterface&         vkd,
227                                          vk::VkDevice                                   device,
228                                          std::vector<vk::VkSemaphore>&  semaphores)
229 {
230         for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
231                 semaphores[ndx] = createSemaphore(vkd, device).disown();
232 }
233
234 void deinitSemaphores (const vk::DeviceInterface&       vkd,
235                                          vk::VkDevice                                   device,
236                                          std::vector<vk::VkSemaphore>&  semaphores)
237 {
238         for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
239         {
240                 if (semaphores[ndx] != (vk::VkSemaphore)0)
241                         vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
242
243                 semaphores[ndx] = (vk::VkSemaphore)0;
244         }
245
246         semaphores.clear();
247 }
248
249 void initFences (const vk::DeviceInterface&     vkd,
250                                  vk::VkDevice                           device,
251                                  std::vector<vk::VkFence>&      fences)
252 {
253         for (size_t ndx = 0; ndx < fences.size(); ndx++)
254                 fences[ndx] = createFence(vkd, device).disown();
255 }
256
257 void deinitFences (const vk::DeviceInterface&   vkd,
258                                    vk::VkDevice                                 device,
259                                    std::vector<vk::VkFence>&    fences)
260 {
261         for (size_t ndx = 0; ndx < fences.size(); ndx++)
262         {
263                 if (fences[ndx] != (vk::VkFence)0)
264                         vkd.destroyFence(device, fences[ndx], DE_NULL);
265
266                 fences[ndx] = (vk::VkFence)0;
267         }
268
269         fences.clear();
270 }
271
272 void cmdRenderFrame (const vk::DeviceInterface& vkd,
273                                          vk::VkCommandBuffer            commandBuffer,
274                                          vk::VkPipelineLayout           pipelineLayout,
275                                          vk::VkPipeline                         pipeline,
276                                          size_t                                         frameNdx,
277                                          deUint32                                       quadCount)
278 {
279         const deUint32 frameNdxValue  = (deUint32)frameNdx;
280
281         vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &frameNdxValue);
282         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
283         vkd.cmdDraw(commandBuffer, quadCount * 6u, 1u, 0u, 0u);
284 }
285
286 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface&   vkd,
287                                                                                                    vk::VkDevice                                 device,
288                                                                                                    vk::VkCommandPool                    commandPool,
289                                                                                                    vk::VkPipelineLayout                 pipelineLayout,
290                                                                                                    vk::VkRenderPass                             renderPass,
291                                                                                                    vk::VkFramebuffer                    framebuffer,
292                                                                                                    vk::VkPipeline                               pipeline,
293                                                                                                    size_t                                               frameNdx,
294                                                                                                    deUint32                                             quadCount,
295                                                                                                    deUint32                                             imageWidth,
296                                                                                                    deUint32                                             imageHeight)
297 {
298         const vk::VkCommandBufferAllocateInfo allocateInfo =
299         {
300                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
301                 DE_NULL,
302
303                 commandPool,
304                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
305                 1
306         };
307         const vk::VkCommandBufferBeginInfo      beginInfo               =
308         {
309                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
310                 DE_NULL,
311                 0u,
312                 DE_NULL
313         };
314
315         vk::Move<vk::VkCommandBuffer>   commandBuffer   (vk::allocateCommandBuffer(vkd, device, &allocateInfo));
316         VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
317
318         {
319                 const vk::VkClearValue                  clearValue                      = vk::makeClearValueColorF32(0.25f, 0.50f, 0.75f, 1.00f);
320                 const vk::VkRenderPassBeginInfo renderPassBeginInfo     =
321                 {
322                         vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
323                         DE_NULL,
324
325                         renderPass,
326                         framebuffer,
327
328                         {
329                                 { (deInt32)0, (deInt32)0 },
330                                 { imageWidth, imageHeight }
331                         },
332                         1u,
333                         &clearValue
334                 };
335                 vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
336         }
337
338         cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, quadCount);
339
340         vkd.cmdEndRenderPass(*commandBuffer);
341
342         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
343         return commandBuffer;
344 }
345
346 void deinitCommandBuffers (const vk::DeviceInterface&                   vkd,
347                                                    vk::VkDevice                                                 device,
348                                                    vk::VkCommandPool                                    commandPool,
349                                                    std::vector<vk::VkCommandBuffer>&    commandBuffers)
350 {
351         for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
352         {
353                 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
354                         vkd.freeCommandBuffers(device, commandPool, 1u,  &commandBuffers[ndx]);
355
356                 commandBuffers[ndx] = (vk::VkCommandBuffer)0;
357         }
358
359         commandBuffers.clear();
360 }
361
362 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface&       vkd,
363                                                                                            vk::VkDevice                                 device,
364                                                                                            deUint32                                             queueFamilyIndex)
365 {
366         const vk::VkCommandPoolCreateInfo createInfo =
367         {
368                 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
369                 DE_NULL,
370                 0u,
371                 queueFamilyIndex
372         };
373
374         return vk::createCommandPool(vkd, device, &createInfo);
375 }
376
377 vk::Move<vk::VkFramebuffer>     createFramebuffer (const vk::DeviceInterface&   vkd,
378                                                                                            vk::VkDevice                                 device,
379                                                                                            vk::VkRenderPass                             renderPass,
380                                                                                            vk::VkImageView                              imageView,
381                                                                                            deUint32                                             width,
382                                                                                            deUint32                                             height)
383 {
384         const vk::VkFramebufferCreateInfo createInfo =
385         {
386                 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
387                 DE_NULL,
388
389                 0u,
390                 renderPass,
391                 1u,
392                 &imageView,
393                 width,
394                 height,
395                 1u
396         };
397
398         return vk::createFramebuffer(vkd, device, &createInfo);
399 }
400
401 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface&   vkd,
402                                                                                    vk::VkDevice                                 device,
403                                                                                    vk::VkImage                                  image,
404                                                                                    vk::VkFormat                                 format)
405 {
406         const vk::VkImageViewCreateInfo createInfo =
407         {
408                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
409                 DE_NULL,
410
411                 0u,
412                 image,
413                 vk::VK_IMAGE_VIEW_TYPE_2D,
414                 format,
415                 vk::makeComponentMappingRGBA(),
416                 {
417                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
418                         0u,
419                         1u,
420                         0u,
421                         1u
422                 }
423         };
424
425         return vk::createImageView(vkd, device, &createInfo, DE_NULL);
426 }
427
428 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd,
429                                                                                          vk::VkDevice                           device,
430                                                                                          vk::VkFormat                           format)
431 {
432         const vk::VkAttachmentDescription       attachments[]                   =
433         {
434                 {
435                         0u,
436                         format,
437                         vk::VK_SAMPLE_COUNT_1_BIT,
438
439                         vk::VK_ATTACHMENT_LOAD_OP_LOAD,
440                         vk::VK_ATTACHMENT_STORE_OP_STORE,
441
442                         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
443                         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
444
445                         // This differs from the usual layout handling in that the
446                         // swapchain image remains in IMAGE_LAYOUT_SHARED_PRESENT_KHR all
447                         // the time. We should not ever transition it away (or discard the
448                         // contents with a transition from UNDEFINED) as the PE is accessing
449                         // the image concurrently with our rendering.
450                         vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
451                         vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
452                 }
453         };
454         const vk::VkAttachmentReference         colorAttachmentRefs[]   =
455         {
456                 {
457                         0u,
458                         vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
459                 }
460         };
461         const vk::VkSubpassDescription          subpasses[]                             =
462         {
463                 {
464                         0u,
465                         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
466                         0u,
467                         DE_NULL,
468
469                         DE_LENGTH_OF_ARRAY(colorAttachmentRefs),
470                         colorAttachmentRefs,
471                         DE_NULL,
472
473                         DE_NULL,
474                         0u,
475                         DE_NULL
476                 }
477         };
478
479         const vk::VkRenderPassCreateInfo        createInfo                              =
480         {
481                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
482                 DE_NULL,
483                 0u,
484
485                 DE_LENGTH_OF_ARRAY(attachments),
486                 attachments,
487
488                 DE_LENGTH_OF_ARRAY(subpasses),
489                 subpasses,
490
491                 0u,
492                 DE_NULL
493         };
494
495         return vk::createRenderPass(vkd, device, &createInfo);
496 }
497
498 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface&     vkd,
499                                                                                  vk::VkDevice                           device,
500                                                                                  vk::VkRenderPass                       renderPass,
501                                                                                  vk::VkPipelineLayout           layout,
502                                                                                  vk::VkShaderModule                     vertexShaderModule,
503                                                                                  vk::VkShaderModule                     fragmentShaderModule,
504                                                                                  deUint32                                       width,
505                                                                                  deUint32                                       height)
506 {
507         const vk::VkSpecializationInfo                          shaderSpecialization    =
508         {
509                 0u,
510                 DE_NULL,
511                 0,
512                 DE_NULL
513         };
514         const vk::VkPipelineShaderStageCreateInfo               stages[]                        =
515         {
516                 {
517                         vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
518                         DE_NULL,
519                         0u,
520                         vk::VK_SHADER_STAGE_VERTEX_BIT,
521                         vertexShaderModule,
522                         "main",
523                         &shaderSpecialization
524                 },
525                 {
526                         vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
527                         DE_NULL,
528                         0u,
529                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
530                         fragmentShaderModule,
531                         "main",
532                         &shaderSpecialization
533                 }
534         };
535         const vk::VkPipelineVertexInputStateCreateInfo  vertexInputState        =
536         {
537                 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
538                 DE_NULL,
539                 0u,
540                 0u,
541                 DE_NULL,
542                 0u,
543                 DE_NULL
544         };
545         const vk::VkPipelineInputAssemblyStateCreateInfo        inputAssemblyState      =
546         {
547                 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
548                 DE_NULL,
549                 0u,
550                 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
551                 VK_FALSE
552         };
553         const vk::VkViewport viewports[] =
554         {
555                 {
556                         0.0f, 0.0f,
557                         (float)width, (float)height,
558                         0.0f, 1.0f
559                 }
560         };
561         const vk::VkRect2D scissors[] =
562         {
563                 {
564                         { 0u, 0u },
565                         { width, height }
566                 }
567         };
568         const vk::VkPipelineViewportStateCreateInfo                     viewportState           =
569         {
570                 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
571                 DE_NULL,
572                 0u,
573
574                 DE_LENGTH_OF_ARRAY(viewports),
575                 viewports,
576                 DE_LENGTH_OF_ARRAY(scissors),
577                 scissors
578         };
579         const vk::VkPipelineRasterizationStateCreateInfo        rasterizationState      =
580         {
581                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
582                 DE_NULL,
583                 0u,
584                 VK_TRUE,
585                 VK_FALSE,
586                 vk::VK_POLYGON_MODE_FILL,
587                 vk::VK_CULL_MODE_NONE,
588                 vk::VK_FRONT_FACE_CLOCKWISE,
589                 VK_FALSE,
590                 0.0f,
591                 0.0f,
592                 0.0f,
593                 1.0f
594         };
595         const vk::VkSampleMask                                                          sampleMask                      = ~0u;
596         const vk::VkPipelineMultisampleStateCreateInfo          multisampleState        =
597         {
598                 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
599                 DE_NULL,
600                 0u,
601                 vk::VK_SAMPLE_COUNT_1_BIT,
602                 VK_FALSE,
603                 0.0f,
604                 &sampleMask,
605                 VK_FALSE,
606                 VK_FALSE
607         };
608         const vk::VkPipelineDepthStencilStateCreateInfo depthStencilState               =
609         {
610                 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
611                 DE_NULL,
612                 0u,
613                 DE_FALSE,
614                 DE_FALSE,
615                 vk::VK_COMPARE_OP_ALWAYS,
616                 DE_FALSE,
617                 DE_FALSE,
618                 {
619                         vk::VK_STENCIL_OP_KEEP,
620                         vk::VK_STENCIL_OP_KEEP,
621                         vk::VK_STENCIL_OP_KEEP,
622                         vk::VK_COMPARE_OP_ALWAYS,
623                         0u,
624                         0u,
625                         0u,
626                 },
627                 {
628                         vk::VK_STENCIL_OP_KEEP,
629                         vk::VK_STENCIL_OP_KEEP,
630                         vk::VK_STENCIL_OP_KEEP,
631                         vk::VK_COMPARE_OP_ALWAYS,
632                         0u,
633                         0u,
634                         0u,
635                 },
636                 0.0f,
637                 1.0f
638         };
639         const vk::VkPipelineColorBlendAttachmentState   attachmentBlendState                    =
640         {
641                 VK_FALSE,
642                 vk::VK_BLEND_FACTOR_ONE,
643                 vk::VK_BLEND_FACTOR_ZERO,
644                 vk::VK_BLEND_OP_ADD,
645                 vk::VK_BLEND_FACTOR_ONE,
646                 vk::VK_BLEND_FACTOR_ZERO,
647                 vk::VK_BLEND_OP_ADD,
648                 (vk::VK_COLOR_COMPONENT_R_BIT|
649                  vk::VK_COLOR_COMPONENT_G_BIT|
650                  vk::VK_COLOR_COMPONENT_B_BIT|
651                  vk::VK_COLOR_COMPONENT_A_BIT),
652         };
653         const vk::VkPipelineColorBlendStateCreateInfo   blendState                              =
654         {
655                 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
656                 DE_NULL,
657                 0u,
658                 DE_FALSE,
659                 vk::VK_LOGIC_OP_COPY,
660                 1u,
661                 &attachmentBlendState,
662                 { 0.0f, 0.0f, 0.0f, 0.0f }
663         };
664         const vk::VkDynamicState                                                        dynamicStates[]         =
665         {
666                 vk::VK_DYNAMIC_STATE_SCISSOR
667         };
668         const vk::VkPipelineDynamicStateCreateInfo                      dynamicState            =
669         {
670                 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
671                 DE_NULL,
672                 0u,
673
674                 DE_LENGTH_OF_ARRAY(dynamicStates),
675                 dynamicStates
676         };
677         const vk::VkGraphicsPipelineCreateInfo                          createInfo                      =
678         {
679                 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
680                 DE_NULL,
681                 0u,
682
683                 DE_LENGTH_OF_ARRAY(stages),
684                 stages,
685                 &vertexInputState,
686                 &inputAssemblyState,
687                 DE_NULL,
688                 &viewportState,
689                 &rasterizationState,
690                 &multisampleState,
691                 &depthStencilState,
692                 &blendState,
693                 &dynamicState,
694                 layout,
695                 renderPass,
696                 0u,
697                 DE_NULL,
698                 0u
699         };
700
701         return vk::createGraphicsPipeline(vkd, device, DE_NULL,  &createInfo);
702 }
703
704 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd,
705                                                                                                          vk::VkDevice                           device)
706 {
707         const vk::VkPushConstantRange                   pushConstants[] =
708         {
709                 {
710                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
711                         0u,
712                         4u
713                 }
714         };
715         const vk::VkPipelineLayoutCreateInfo    createInfo      =
716         {
717                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
718                 DE_NULL,
719                 0u,
720
721                 0u,
722                 DE_NULL,
723
724                 DE_LENGTH_OF_ARRAY(pushConstants),
725                 pushConstants,
726         };
727
728         return vk::createPipelineLayout(vkd, device, &createInfo);
729 }
730
731 struct TestConfig
732 {
733         vk::wsi::Type                   wsiType;
734         Scaling                                 scaling;
735         bool                                    useSharedPresentableImage;
736         vk::VkPresentModeKHR    presentMode;
737 };
738
739 class SharedPresentableImageTestInstance : public TestInstance
740 {
741 public:
742                                                                                                         SharedPresentableImageTestInstance      (Context& context, const TestConfig& testConfig);
743                                                                                                         ~SharedPresentableImageTestInstance     (void);
744
745         tcu::TestStatus                                                                 iterate                                                         (void);
746
747 private:
748         const TestConfig                                                                m_testConfig;
749         const deUint32                                                                  m_quadCount;
750         const vk::PlatformInterface&                                    m_vkp;
751         const Extensions                                                                m_instanceExtensions;
752         const vk::Unique<vk::VkInstance>                                m_instance;
753         const vk::InstanceDriver                                                m_vki;
754         const vk::VkPhysicalDevice                                              m_physicalDevice;
755         const de::UniquePtr<vk::wsi::Display>                   m_nativeDisplay;
756         const de::UniquePtr<vk::wsi::Window>                    m_nativeWindow;
757         const vk::Unique<vk::VkSurfaceKHR>                              m_surface;
758
759         const deUint32                                                                  m_queueFamilyIndex;
760         const Extensions                                                                m_deviceExtensions;
761         const vk::Unique<vk::VkDevice>                                  m_device;
762         const vk::DeviceDriver                                                  m_vkd;
763         const vk::VkQueue                                                               m_queue;
764
765         const vk::Unique<vk::VkCommandPool>                             m_commandPool;
766         const vk::Unique<vk::VkShaderModule>                    m_vertexShaderModule;
767         const vk::Unique<vk::VkShaderModule>                    m_fragmentShaderModule;
768         const vk::Unique<vk::VkPipelineLayout>                  m_pipelineLayout;
769
770         vk::VkImageUsageFlags                                                   m_supportedUsageFlags;
771         const vk::VkSurfaceCapabilitiesKHR                              m_surfaceProperties;
772         const vector<vk::VkSurfaceFormatKHR>                    m_surfaceFormats;
773         const vector<vk::VkPresentModeKHR>                              m_presentModes;
774
775         tcu::ResultCollector                                                    m_resultCollector;
776
777         vk::Move<vk::VkSwapchainKHR>                                    m_swapchain;
778         vk::VkImage                                                                             m_swapchainImage;                         // NOTE: not owning. lifetime managed by swapchain
779         vk::Move<vk::VkImageView>                                               m_swapchainImageView;
780         vk::Move<vk::VkFramebuffer>                                             m_framebuffer;
781
782         vk::Move<vk::VkRenderPass>                                              m_renderPass;
783         vk::Move<vk::VkPipeline>                                                m_pipeline;
784
785         std::vector<vk::VkCommandBuffer>                                m_commandBuffers;
786         std::vector<vk::VkSemaphore>                                    m_renderSemaphores;
787         std::vector<vk::VkFence>                                                m_fences;
788
789         std::vector<vk::VkSwapchainCreateInfoKHR>               m_swapchainConfigs;
790         size_t                                                                                  m_swapchainConfigNdx;
791
792         const size_t                                                                    m_frameCount;
793         size_t                                                                                  m_frameNdx;
794
795         const size_t                                                                    m_maxOutOfDateCount;
796         size_t                                                                                  m_outOfDateCount;
797
798         void                                                                                    initSwapchainResources          (void);
799         void                                                                                    deinitSwapchainResources        (void);
800         void                                                                                    render                                          (void);
801 };
802
803 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR                                            surface,
804                                                                                                                                         deUint32                                                                queueFamilyIndex,
805                                                                                                                                         Scaling                                                                 scaling,
806                                                                                                                                         const vk::VkSurfaceCapabilitiesKHR&             properties,
807                                                                                                                                         const vector<vk::VkSurfaceFormatKHR>&   formats,
808                                                                                                                                         const vector<vk::VkPresentModeKHR>&             presentModes,
809                                                                                                                                         vk::VkPresentModeKHR                                    presentMode,
810                                                                                                                                         vk::VkImageUsageFlags                                   supportedImageUsage)
811 {
812         const deUint32                                                  imageLayers                     = 1u;
813         const vk::VkImageUsageFlags                             imageUsage                      = properties.supportedUsageFlags & supportedImageUsage;
814         const vk::VkBool32                                              clipped                         = VK_FALSE;
815         vector<vk::VkSwapchainCreateInfoKHR>    createInfos;
816
817         const deUint32                          imageWidth              = scaling == SCALING_NONE
818                                                                                                 ? (properties.currentExtent.width != 0xFFFFFFFFu
819                                                                                                         ? properties.currentExtent.width
820                                                                                                         : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2)))
821                                                                                                 : (scaling == SCALING_UP
822                                                                                                         ? de::max(31u, properties.minImageExtent.width)
823                                                                                                         : properties.maxImageExtent.width);
824         const deUint32                          imageHeight             = scaling == SCALING_NONE
825                                                                                                 ? (properties.currentExtent.height != 0xFFFFFFFFu
826                                                                                                         ? properties.currentExtent.height
827                                                                                                         : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2)))
828                                                                                                 : (scaling == SCALING_UP
829                                                                                                         ? de::max(31u, properties.minImageExtent.height)
830                                                                                                         : properties.maxImageExtent.height);
831         const vk::VkExtent2D            imageSize               = { imageWidth, imageHeight };
832
833         {
834                 size_t presentModeNdx;
835
836                 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
837                 {
838                         if (presentModes[presentModeNdx] == presentMode)
839                                 break;
840                 }
841
842                 if (presentModeNdx == presentModes.size())
843                         TCU_THROW(NotSupportedError, "Present mode not supported");
844         }
845
846         for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
847         {
848                 for (vk::VkSurfaceTransformFlagsKHR transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u)
849                 {
850                         if ((properties.supportedTransforms & transform) == 0)
851                                 continue;
852
853                         for (vk::VkCompositeAlphaFlagsKHR alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u)
854                         {
855                                 if ((alpha & properties.supportedCompositeAlpha) == 0)
856                                         continue;
857
858                                 const vk::VkSurfaceTransformFlagBitsKHR preTransform    = (vk::VkSurfaceTransformFlagBitsKHR)transform;
859                                 const vk::VkCompositeAlphaFlagBitsKHR   compositeAlpha  = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
860                                 const vk::VkFormat                                              imageFormat             = formats[formatNdx].format;
861                                 const vk::VkColorSpaceKHR                               imageColorSpace = formats[formatNdx].colorSpace;
862                                 const vk::VkSwapchainCreateInfoKHR              createInfo              =
863                                 {
864                                         vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
865                                         DE_NULL,
866                                         0u,
867                                         surface,
868                                         1,                                                                                                              // Always 1 image for a shared presentable image swapchain.
869                                         imageFormat,
870                                         imageColorSpace,
871                                         imageSize,
872                                         imageLayers,
873                                         imageUsage,
874                                         vk::VK_SHARING_MODE_EXCLUSIVE,
875                                         1u,
876                                         &queueFamilyIndex,
877                                         preTransform,
878                                         compositeAlpha,
879                                         presentMode,
880                                         clipped,
881                                         (vk::VkSwapchainKHR)0
882                                 };
883
884                                 createInfos.push_back(createInfo);
885                         }
886                 }
887         }
888
889         return createInfos;
890 }
891
892 vk::VkSurfaceCapabilitiesKHR getPhysicalDeviceSurfaceCapabilities (const vk::InstanceInterface& vki,
893                                                                                                                                    vk::VkPhysicalDevice                 physicalDevice,
894                                                                                                                                    vk::VkSurfaceKHR                             surface,
895                                                                                                                                    vk::VkImageUsageFlags*               usage)
896 {
897         const vk::VkPhysicalDeviceSurfaceInfo2KHR       info    =
898         {
899                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
900                 DE_NULL,
901
902                 surface
903         };
904         vk::VkSharedPresentSurfaceCapabilitiesKHR       sharedCapabilities;
905         vk::VkSurfaceCapabilities2KHR                           capabilities;
906
907         sharedCapabilities.sType        = vk::VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR;
908         sharedCapabilities.pNext        = DE_NULL;
909
910         capabilities.sType                      = vk::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
911         capabilities.pNext                      = &sharedCapabilities;
912
913         VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, &info, &capabilities));
914
915         TCU_CHECK(sharedCapabilities.sharedPresentSupportedUsageFlags & vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
916         *usage = sharedCapabilities.sharedPresentSupportedUsageFlags;
917
918         return capabilities.surfaceCapabilities;
919 }
920
921 SharedPresentableImageTestInstance::SharedPresentableImageTestInstance (Context& context, const TestConfig& testConfig)
922         : TestInstance                          (context)
923         , m_testConfig                          (testConfig)
924         , m_quadCount                           (16u)
925         , m_vkp                                         (context.getPlatformInterface())
926         , m_instanceExtensions          (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
927         , m_instance                            (createInstanceWithWsi(m_vkp, m_instanceExtensions, testConfig.wsiType))
928         , m_vki                                         (m_vkp, *m_instance)
929         , m_physicalDevice                      (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
930         , m_nativeDisplay                       (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
931         , m_nativeWindow                        (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
932         , m_surface                                     (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
933
934         , m_queueFamilyIndex            (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
935         , m_deviceExtensions            (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
936         , m_device                                      (createDeviceWithWsi(m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useSharedPresentableImage))
937         , m_vkd                                         (m_vki, *m_device)
938         , m_queue                                       (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
939
940         , m_commandPool                         (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
941         , m_vertexShaderModule          (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
942         , m_fragmentShaderModule        (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
943         , m_pipelineLayout                      (createPipelineLayout(m_vkd, *m_device))
944
945         , m_supportedUsageFlags         (0u)
946         , m_surfaceProperties           (getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface, &m_supportedUsageFlags))
947         , m_surfaceFormats                      (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
948         , m_presentModes                        (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
949
950         , m_swapchainConfigs            (generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode, m_supportedUsageFlags))
951         , m_swapchainConfigNdx          (0u)
952
953         , m_frameCount                          (60u * 5u)
954         , m_frameNdx                            (0u)
955
956         , m_maxOutOfDateCount           (20u)
957         , m_outOfDateCount                      (0u)
958 {
959         {
960                 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
961                 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
962                 m_context.getTestContext().getLog() << TestLog::Message << "SharedPresentSupportedUsageFlags: " << m_supportedUsageFlags << TestLog::EndMessage;
963
964         }
965 }
966
967 SharedPresentableImageTestInstance::~SharedPresentableImageTestInstance (void)
968 {
969         deinitSwapchainResources();
970 }
971
972 void SharedPresentableImageTestInstance::initSwapchainResources (void)
973 {
974         const size_t            fenceCount      = 6;
975         const deUint32          imageWidth      = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
976         const deUint32          imageHeight     = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
977         const vk::VkFormat      imageFormat     = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
978
979         m_swapchain                             = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
980         m_swapchainImage                = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain).front();
981
982         m_renderPass                    = createRenderPass(m_vkd, *m_device, imageFormat);
983         m_pipeline                              = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
984
985         m_swapchainImageView    = createImageView(m_vkd, *m_device, m_swapchainImage, imageFormat);
986         m_framebuffer                   = createFramebuffer(m_vkd, *m_device, *m_renderPass, *m_swapchainImageView, imageWidth, imageHeight);
987
988         m_renderSemaphores              = std::vector<vk::VkSemaphore>(fenceCount, (vk::VkSemaphore)0);
989         m_fences                                = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
990         m_commandBuffers                = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
991
992         initSemaphores(m_vkd, *m_device, m_renderSemaphores);
993
994         initFences(m_vkd, *m_device, m_fences);
995
996         // Unlike a traditional swapchain, where we'd acquire a new image from the
997         // PE every frame, a shared image swapchain has a single image that is
998         // acquired upfront. We acquire it here, transition it to the proper layout,
999         // and present it.
1000
1001         // Acquire the one image
1002         const deUint64                          foreverNs               = 0xFFFFFFFFFFFFFFFFul;
1003         vk::Move<vk::VkSemaphore>       semaphore(createSemaphore(m_vkd, *m_device));
1004         deUint32                                        imageIndex              = 42;   // initialize to junk value
1005
1006         VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, *semaphore, 0u, &imageIndex));
1007         TCU_CHECK(imageIndex == 0);
1008
1009         // Transition to IMAGE_LAYOUT_SHARED_PRESENT_KHR
1010         const vk::VkCommandBufferAllocateInfo allocateInfo =
1011         {
1012                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1013                 DE_NULL,
1014                 *m_commandPool,
1015                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1016                 1
1017         };
1018         const vk::VkCommandBufferBeginInfo      beginInfo               =
1019         {
1020                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1021                 DE_NULL,
1022                 0u,
1023                 DE_NULL
1024         };
1025
1026         const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (vk::allocateCommandBuffer(m_vkd, *m_device, &allocateInfo));
1027         VK_CHECK(m_vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
1028
1029         const vk::VkImageMemoryBarrier barrier = {
1030                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1031                 DE_NULL,
1032                 0,
1033                 0,
1034                 vk::VK_IMAGE_LAYOUT_UNDEFINED,
1035                 vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
1036                 VK_QUEUE_FAMILY_IGNORED,
1037                 VK_QUEUE_FAMILY_IGNORED,
1038                 m_swapchainImage,
1039                 {
1040                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
1041                         0,
1042                         1,
1043                         0,
1044                         1
1045                 },
1046         };
1047
1048         m_vkd.cmdPipelineBarrier(*commandBuffer,
1049                                                         vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1050                                                         vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1051                                                         0u,
1052                                                         0, DE_NULL,
1053                                                         0, DE_NULL,
1054                                                         1, &barrier);
1055
1056         VK_CHECK(m_vkd.endCommandBuffer(*commandBuffer));
1057
1058         const vk::VkSubmitInfo submitInfo =
1059         {
1060                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1061                 DE_NULL,
1062                 1, &*semaphore, DE_NULL,
1063                 1, &*commandBuffer,
1064                 0, DE_NULL,
1065         };
1066
1067         VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, (vk::VkFence)0));
1068         VK_CHECK(m_vkd.queueWaitIdle(m_queue));
1069 }
1070
1071 void SharedPresentableImageTestInstance::deinitSwapchainResources (void)
1072 {
1073         VK_CHECK(m_vkd.queueWaitIdle(m_queue));
1074
1075         deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
1076         deinitFences(m_vkd, *m_device, m_fences);
1077         deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
1078
1079         m_framebuffer   = vk::Move<vk::VkFramebuffer>();
1080         m_swapchainImageView = vk::Move<vk::VkImageView>();
1081         m_swapchainImage = (vk::VkImage)0;
1082
1083         m_swapchain             = vk::Move<vk::VkSwapchainKHR>();
1084         m_renderPass    = vk::Move<vk::VkRenderPass>();
1085         m_pipeline              = vk::Move<vk::VkPipeline>();
1086 }
1087
1088 void SharedPresentableImageTestInstance::render (void)
1089 {
1090         const deUint64          foreverNs               = 0xFFFFFFFFFFFFFFFFul;
1091         const vk::VkFence       fence                   = m_fences[m_frameNdx % m_fences.size()];
1092         const deUint32          width                   = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
1093         const deUint32          height                  = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
1094
1095         // Throttle execution
1096         if (m_frameNdx >= m_fences.size())
1097         {
1098                 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
1099                 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
1100
1101                 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
1102                 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
1103         }
1104
1105         deUint32                        imageIndex = 0;         // There is only one image.
1106         const vk::VkSemaphore currentRenderSemaphore = m_renderSemaphores[m_frameNdx % m_renderSemaphores.size()];
1107
1108         const bool willPresent = m_swapchainConfigs[m_swapchainConfigNdx].presentMode == vk::VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR || !m_frameNdx;
1109
1110         // Create command buffer
1111         m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, *m_framebuffer, *m_pipeline, m_frameNdx, m_quadCount, width, height).disown();
1112
1113         // Submit command buffer
1114         {
1115                 const vk::VkSubmitInfo                  submitInfo              =
1116                 {
1117                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1118                         DE_NULL,
1119                         0u,
1120                         DE_NULL,
1121                         DE_NULL,
1122                         1u,
1123                         &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
1124                         willPresent ? 1u : 0u,    // Only signal the semaphore if we're going to call QueuePresent.
1125                         &currentRenderSemaphore
1126                 };
1127
1128                 // With a traditional swapchain, we'd fence on completion of
1129                 // AcquireNextImage. We never call that for a shared image swapchain, so
1130                 // fence on completion of the rendering work instead. A real shared
1131                 // image application would want a more substantial pacing mechanism.
1132                 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
1133         }
1134
1135         // DEMAND_REFRESH requires us to call QueuePresent whenever we want to be
1136         // assured the PE has picked up a new frame. The PE /may/ also pick up
1137         // changes whenever it likes.
1138         //
1139         // For CONTINUOUS_REFRESH, we need to just call QueuePresent once on the
1140         // first frame to kick things off.
1141         if (willPresent)
1142         {
1143
1144                 // Present frame
1145                 vk::VkResult result;
1146                 const vk::VkPresentInfoKHR presentInfo =
1147                 {
1148                         vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1149                         DE_NULL,
1150                         1u,
1151                         &currentRenderSemaphore,
1152                         1u,
1153                         &*m_swapchain,
1154                         &imageIndex,
1155                         &result
1156                 };
1157
1158                 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1159                 VK_CHECK(result);
1160
1161         }
1162
1163         // With either present mode, we can call GetSwapchainStatus at any time
1164         // to detect possible OUT_OF_DATE conditions. Let's do that every frame.
1165
1166         const vk::VkResult swapchainStatus = m_vkd.getSwapchainStatusKHR(*m_device, *m_swapchain);
1167         VK_CHECK(swapchainStatus);
1168 }
1169
1170 tcu::TestStatus SharedPresentableImageTestInstance::iterate (void)
1171 {
1172         // Initialize swapchain specific resources
1173         // Render test
1174         try
1175         {
1176                 if (m_frameNdx == 0)
1177                 {
1178                         if (m_outOfDateCount == 0)
1179                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage;
1180
1181                         initSwapchainResources();
1182                 }
1183
1184                 render();
1185         }
1186         catch (const vk::Error& error)
1187         {
1188                 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1189                 {
1190                         m_swapchainConfigs = generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode, m_supportedUsageFlags);
1191
1192                         if (m_outOfDateCount < m_maxOutOfDateCount)
1193                         {
1194                                 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1195                                 deinitSwapchainResources();
1196                                 m_frameNdx = 0;
1197                                 m_outOfDateCount++;
1198
1199                                 return tcu::TestStatus::incomplete();
1200                         }
1201                         else
1202                         {
1203                                 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1204                                 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1205                         }
1206                 }
1207                 else
1208                 {
1209                         m_resultCollector.fail(error.what());
1210                 }
1211
1212                 deinitSwapchainResources();
1213
1214                 m_swapchainConfigNdx++;
1215                 m_frameNdx = 0;
1216                 m_outOfDateCount = 0;
1217
1218                 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1219                         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1220                 else
1221                         return tcu::TestStatus::incomplete();
1222         }
1223
1224         m_frameNdx++;
1225
1226         if (m_frameNdx >= m_frameCount)
1227         {
1228                 m_frameNdx = 0;
1229                 m_outOfDateCount = 0;
1230                 m_swapchainConfigNdx++;
1231
1232                 deinitSwapchainResources();
1233
1234                 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1235                         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1236                 else
1237                         return tcu::TestStatus::incomplete();
1238         }
1239         else
1240                 return tcu::TestStatus::incomplete();
1241 }
1242
1243 struct Programs
1244 {
1245         static void init (vk::SourceCollections& dst, TestConfig)
1246         {
1247                 dst.glslSources.add("quad-vert") << glu::VertexSource(
1248                         "#version 450\n"
1249                         "out gl_PerVertex {\n"
1250                         "\tvec4 gl_Position;\n"
1251                         "};\n"
1252                         "layout(location = 0) out highp uint quadIndex;\n"
1253                         "highp float;\n"
1254                         "void main (void) {\n"
1255                         "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1256                         "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1257                         "\tquadIndex = gl_VertexIndex / 6;\n"
1258                         "}\n");
1259                 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1260                         "#version 310 es\n"
1261                         "layout(location = 0) flat in highp uint quadIndex;\n"
1262                         "layout(location = 0) out highp vec4 o_color;\n"
1263                         "layout(push_constant) uniform PushConstant {\n"
1264                         "\thighp uint frameNdx;\n"
1265                         "} pushConstants;\n"
1266                         "void main (void)\n"
1267                         "{\n"
1268                         "\thighp uint frameNdx = pushConstants.frameNdx;\n"
1269                         "\thighp uint cellX = bitfieldExtract(uint(gl_FragCoord.x), 7, 10);\n"
1270                         "\thighp uint cellY = bitfieldExtract(uint(gl_FragCoord.y), 7, 10);\n"
1271                         "\thighp uint x = quadIndex ^ (frameNdx + (uint(gl_FragCoord.x) >> cellX));\n"
1272                         "\thighp uint y = quadIndex ^ (frameNdx + (uint(gl_FragCoord.y) >> cellY));\n"
1273                         "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1274                         "\t             +  64u * bitfieldExtract(y, 1, 1)\n"
1275                         "\t             +  32u * bitfieldExtract(x, 3, 1);\n"
1276                         "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1277                         "\t             +  64u * bitfieldExtract(x, 2, 1)\n"
1278                         "\t             +  32u * bitfieldExtract(y, 3, 1);\n"
1279                         "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1280                         "\t             +  64u * bitfieldExtract(y, 2, 1)\n"
1281                         "\t             +  32u * bitfieldExtract(x, 4, 1);\n"
1282                         "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1283                         "}\n");
1284         }
1285 };
1286
1287 } // anonymous
1288
1289 void createSharedPresentableImageTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1290 {
1291         const struct
1292         {
1293                 Scaling         scaling;
1294                 const char*     name;
1295         } scaling [] =
1296         {
1297                 { SCALING_NONE, "scale_none"    },
1298                 { SCALING_UP,   "scale_up"              },
1299                 { SCALING_DOWN, "scale_down"    }
1300         };
1301         const struct
1302         {
1303                 vk::VkPresentModeKHR    mode;
1304                 const char*                             name;
1305         } presentModes[] =
1306         {
1307                 { vk::VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,                        "demand"                        },
1308                 { vk::VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR,            "continuous"            },
1309         };
1310
1311         for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
1312         {
1313                 if (scaling[scalingNdx].scaling == SCALING_NONE || wsiTypeSupportsScaling(wsiType))
1314                 {
1315                         de::MovePtr<tcu::TestCaseGroup> scaleGroup      (new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name));
1316
1317                         for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1318                         {
1319
1320                                 const char* const                               name            = presentModes[presentModeNdx].name;
1321                                 TestConfig                                              config;
1322
1323                                 config.wsiType                                  = wsiType;
1324                                 config.useSharedPresentableImage= true;
1325                                 config.scaling                                  = scaling[scalingNdx].scaling;
1326                                 config.presentMode                              = presentModes[presentModeNdx].mode;
1327
1328                                 scaleGroup->addChild(new vkt::InstanceFactory1<SharedPresentableImageTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1329                         }
1330
1331                         testGroup->addChild(scaleGroup.release());
1332                 }
1333         }
1334 }
1335
1336 } // wsi
1337 } // vkt