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