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