Merge vk-gl-cts/vulkan-cts-1.1.0 into vk-gl-cts/vulkan-cts-1.1.1
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / wsi / vktWsiColorSpaceTests.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 VkSwapchain Tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktWsiSwapchainTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkWsiPlatform.hpp"
40 #include "vkWsiUtil.hpp"
41 #include "vkAllocationCallbackUtil.hpp"
42
43 #include "tcuTestLog.hpp"
44 #include "tcuFormatUtil.hpp"
45 #include "tcuPlatform.hpp"
46 #include "tcuResultCollector.hpp"
47
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 #include "deArrayUtil.hpp"
51 #include "deSharedPtr.hpp"
52
53 #include <limits>
54
55 namespace vkt
56 {
57 namespace wsi
58 {
59
60 namespace
61 {
62
63 using namespace vk;
64 using namespace vk::wsi;
65
66 using tcu::TestLog;
67 using tcu::Maybe;
68 using tcu::UVec2;
69
70 using de::MovePtr;
71 using de::UniquePtr;
72
73 using std::string;
74 using std::vector;
75
76 typedef vector<VkExtensionProperties> Extensions;
77
78 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
79 {
80         for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
81                  requiredExtName != requiredExtensions.end();
82                  ++requiredExtName)
83         {
84                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
85                         TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
86         }
87 }
88
89 Move<VkInstance> createInstanceWithWsi (const PlatformInterface&                vkp,
90                                                                                 deUint32                                                version,
91                                                                                 const Extensions&                               supportedExtensions,
92                                                                                 Type                                                    wsiType,
93                                                                                 const VkAllocationCallbacks*    pAllocator      = DE_NULL)
94 {
95         vector<string>  extensions;
96
97         extensions.push_back("VK_KHR_surface");
98         extensions.push_back(getExtensionName(wsiType));
99
100         // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
101         // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
102         // but using them without enabling the extension is not allowed. Thus we have
103         // two options:
104         //
105         // 1) Filter out non-core formats to stay within valid usage.
106         //
107         // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
108         //
109         // We opt for (2) as it provides basic coverage for the extension as a bonus.
110         if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
111                 extensions.push_back("VK_EXT_swapchain_colorspace");
112
113         checkAllSupported(supportedExtensions, extensions);
114
115         return createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator);
116 }
117
118 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
119 {
120         VkPhysicalDeviceFeatures features;
121         deMemset(&features, 0, sizeof(features));
122         return features;
123 }
124
125 Move<VkDevice> createDeviceWithWsi (const InstanceInterface&            vki,
126                                                                         VkPhysicalDevice                                physicalDevice,
127                                                                         const Extensions&                               supportedExtensions,
128                                                                         const deUint32                                  queueFamilyIndex,
129                                                                         const VkAllocationCallbacks*    pAllocator = DE_NULL)
130 {
131         const float                                             queuePriorities[]       = { 1.0f };
132         const VkDeviceQueueCreateInfo   queueInfos[]            =
133         {
134                 {
135                         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
136                         DE_NULL,
137                         (VkDeviceQueueCreateFlags)0,
138                         queueFamilyIndex,
139                         DE_LENGTH_OF_ARRAY(queuePriorities),
140                         &queuePriorities[0]
141                 }
142         };
143         const VkPhysicalDeviceFeatures  features                = getDeviceFeaturesForWsi();
144         const char* const                               extensions[]    = { "VK_KHR_swapchain" };
145         const VkDeviceCreateInfo                deviceParams    =
146         {
147                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
148                 DE_NULL,
149                 (VkDeviceCreateFlags)0,
150                 DE_LENGTH_OF_ARRAY(queueInfos),
151                 &queueInfos[0],
152                 0u,                                                                     // enabledLayerCount
153                 DE_NULL,                                                        // ppEnabledLayerNames
154                 DE_LENGTH_OF_ARRAY(extensions),         // enabledExtensionCount
155                 DE_ARRAY_BEGIN(extensions),                     // ppEnabledExtensionNames
156                 &features
157         };
158
159         if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[0])))
160                 TCU_THROW(NotSupportedError, (string(extensions[0]) + " is not supported").c_str());
161
162         return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
163 }
164
165 deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
166 {
167         deUint32        numFamilies             = 0;
168
169         vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
170
171         return numFamilies;
172 }
173
174 vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
175 {
176         const deUint32          numTotalFamilyIndices   = getNumQueueFamilyIndices(vki, physicalDevice);
177         vector<deUint32>        supportedFamilyIndices;
178
179         for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
180         {
181                 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
182                         supportedFamilyIndices.push_back(queueFamilyNdx);
183         }
184
185         return supportedFamilyIndices;
186 }
187
188 deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
189 {
190         const vector<deUint32>  supportedFamilyIndices  = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
191
192         if (supportedFamilyIndices.empty())
193                 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
194
195         return supportedFamilyIndices[0];
196 }
197
198 struct InstanceHelper
199 {
200         const vector<VkExtensionProperties>     supportedExtensions;
201         const Unique<VkInstance>                        instance;
202         const InstanceDriver                            vki;
203
204         InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
205                 : supportedExtensions   (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
206                                                                                                                                           DE_NULL))
207                 , instance                              (createInstanceWithWsi(context.getPlatformInterface(),
208                                                                                                            context.getUsedApiVersion(),
209                                                                                                            supportedExtensions,
210                                                                                                            wsiType,
211                                                                                                            pAllocator))
212                 , vki                                   (context.getPlatformInterface(), *instance)
213         {}
214 };
215
216 struct DeviceHelper
217 {
218         const VkPhysicalDevice  physicalDevice;
219         const deUint32                  queueFamilyIndex;
220         const Unique<VkDevice>  device;
221         const DeviceDriver              vkd;
222         const VkQueue                   queue;
223
224         DeviceHelper (Context&                                          context,
225                                   const InstanceInterface&              vki,
226                                   VkInstance                                    instance,
227                                   VkSurfaceKHR                                  surface,
228                                   const VkAllocationCallbacks*  pAllocator = DE_NULL)
229                 : physicalDevice        (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
230                 , queueFamilyIndex      (chooseQueueFamilyIndex(vki, physicalDevice, surface))
231                 , device                        (createDeviceWithWsi(vki,
232                                                                                                  physicalDevice,
233                                                                                                  enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
234                                                                                                  queueFamilyIndex,
235                                                                                                  pAllocator))
236                 , vkd                           (vki, *device)
237                 , queue                         (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
238         {
239         }
240 };
241
242 MovePtr<Display> createDisplay (const vk::Platform&     platform,
243                                                                 const Extensions&       supportedExtensions,
244                                                                 Type                            wsiType)
245 {
246         try
247         {
248                 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
249         }
250         catch (const tcu::NotSupportedError& e)
251         {
252                 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
253                 {
254                         // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
255                         // must support creating native display & window for that WSI type.
256                         throw tcu::TestError(e.getMessage());
257                 }
258                 else
259                         throw;
260         }
261 }
262
263 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
264 {
265         try
266         {
267                 return MovePtr<Window>(display.createWindow(initialSize));
268         }
269         catch (const tcu::NotSupportedError& e)
270         {
271                 // See createDisplay - assuming that wsi::Display was supported platform port
272                 // should also support creating a window.
273                 throw tcu::TestError(e.getMessage());
274         }
275 }
276
277 struct NativeObjects
278 {
279         const UniquePtr<Display>        display;
280         const UniquePtr<Window>         window;
281
282         NativeObjects (Context&                         context,
283                                    const Extensions&    supportedExtensions,
284                                    Type                                 wsiType,
285                                    const Maybe<UVec2>&  initialWindowSize = tcu::nothing<UVec2>())
286                 : display       (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
287                 , window        (createWindow(*display, initialWindowSize))
288         {}
289 };
290
291 enum TestDimension
292 {
293         TEST_DIMENSION_MIN_IMAGE_COUNT = 0,     //!< Test all supported image counts
294         TEST_DIMENSION_IMAGE_FORMAT,            //!< Test all supported formats
295         TEST_DIMENSION_IMAGE_EXTENT,            //!< Test various (supported) extents
296         TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
297         TEST_DIMENSION_IMAGE_USAGE,
298         TEST_DIMENSION_IMAGE_SHARING_MODE,
299         TEST_DIMENSION_PRE_TRANSFORM,
300         TEST_DIMENSION_COMPOSITE_ALPHA,
301         TEST_DIMENSION_PRESENT_MODE,
302         TEST_DIMENSION_CLIPPED,
303
304         TEST_DIMENSION_LAST
305 };
306
307 struct TestParameters
308 {
309         Type                    wsiType;
310         TestDimension   dimension;
311
312         TestParameters (Type wsiType_, TestDimension dimension_)
313                 : wsiType       (wsiType_)
314                 , dimension     (dimension_)
315         {}
316
317         TestParameters (void)
318                 : wsiType       (TYPE_LAST)
319                 , dimension     (TEST_DIMENSION_LAST)
320         {}
321 };
322
323 struct GroupParameters
324 {
325         typedef FunctionInstance1<TestParameters>::Function     Function;
326
327         Type            wsiType;
328         Function        function;
329
330         GroupParameters (Type wsiType_, Function function_)
331                 : wsiType       (wsiType_)
332                 , function      (function_)
333         {}
334
335         GroupParameters (void)
336                 : wsiType       (TYPE_LAST)
337                 , function      ((Function)DE_NULL)
338         {}
339 };
340
341 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type                                              wsiType,
342                                                                                                           const InstanceInterface&      vki,
343                                                                                                           VkPhysicalDevice                      physicalDevice,
344                                                                                                           VkSurfaceKHR                          surface,
345                                                                                                           VkSurfaceFormatKHR            surfaceFormat,
346                                                                                                           const tcu::UVec2&                     desiredSize,
347                                                                                                           deUint32                                      desiredImageCount)
348 {
349         const VkSurfaceCapabilitiesKHR          capabilities            = getPhysicalDeviceSurfaceCapabilities(vki,
350                                                                                                                                                                                                    physicalDevice,
351                                                                                                                                                                                                    surface);
352         const PlatformProperties&                       platformProperties      = getPlatformProperties(wsiType);
353         const VkSurfaceTransformFlagBitsKHR transform                   = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
354         const VkSwapchainCreateInfoKHR          parameters                      =
355         {
356                 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
357                 DE_NULL,
358                 (VkSwapchainCreateFlagsKHR)0,
359                 surface,
360                 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
361                 surfaceFormat.format,
362                 surfaceFormat.colorSpace,
363                 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
364                         ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
365                 1u,                                                                     // imageArrayLayers
366                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
367                 VK_SHARING_MODE_EXCLUSIVE,
368                 0u,
369                 (const deUint32*)DE_NULL,
370                 transform,
371                 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
372                 VK_PRESENT_MODE_FIFO_KHR,
373                 VK_FALSE,                                                       // clipped
374                 (VkSwapchainKHR)0                                       // oldSwapchain
375         };
376
377         return parameters;
378 }
379
380 typedef de::SharedPtr<Unique<VkImageView> >             ImageViewSp;
381 typedef de::SharedPtr<Unique<VkFramebuffer> >   FramebufferSp;
382
383 class TriangleRenderer
384 {
385 public:
386                                                                         TriangleRenderer        (const DeviceInterface&         vkd,
387                                                                                                                  const VkDevice                         device,
388                                                                                                                  Allocator&                                     allocator,
389                                                                                                                  const BinaryCollection&        binaryRegistry,
390                                                                                                                  const vector<VkImage>          swapchainImages,
391                                                                                                                  const VkFormat                         framebufferFormat,
392                                                                                                                  const UVec2&                           renderSize);
393                                                                         ~TriangleRenderer       (void);
394
395         void                                                    recordFrame                     (VkCommandBuffer                        cmdBuffer,
396                                                                                                                  deUint32                                       imageNdx,
397                                                                                                                  deUint32                                       frameNdx) const;
398
399         static void                                             getPrograms                     (SourceCollections& dst);
400
401 private:
402         static Move<VkRenderPass>               createRenderPass        (const DeviceInterface&         vkd,
403                                                                                                                  const VkDevice                         device,
404                                                                                                                  const VkFormat                         colorAttachmentFormat);
405         static Move<VkPipelineLayout>   createPipelineLayout(const DeviceInterface&             vkd,
406                                                                                                                  VkDevice                                       device);
407         static Move<VkPipeline>                 createPipeline          (const DeviceInterface&         vkd,
408                                                                                                                  const VkDevice                         device,
409                                                                                                                  const VkRenderPass                     renderPass,
410                                                                                                                  const VkPipelineLayout         pipelineLayout,
411                                                                                                                  const BinaryCollection&        binaryCollection,
412                                                                                                                  const UVec2&                           renderSize);
413
414         static Move<VkImageView>                createAttachmentView(const DeviceInterface&             vkd,
415                                                                                                                  const VkDevice                         device,
416                                                                                                                  const VkImage                          image,
417                                                                                                                  const VkFormat                         format);
418         static Move<VkFramebuffer>              createFramebuffer       (const DeviceInterface&         vkd,
419                                                                                                                  const VkDevice                         device,
420                                                                                                                  const VkRenderPass                     renderPass,
421                                                                                                                  const VkImageView                      colorAttachment,
422                                                                                                                  const UVec2&                           renderSize);
423
424         static Move<VkBuffer>                   createBuffer            (const DeviceInterface&         vkd,
425                                                                                                                  VkDevice                                       device,
426                                                                                                                  VkDeviceSize                           size,
427                                                                                                                  VkBufferUsageFlags                     usage);
428
429         const DeviceInterface&                  m_vkd;
430
431         const vector<VkImage>                   m_swapchainImages;
432         const tcu::UVec2                                m_renderSize;
433
434         const Unique<VkRenderPass>              m_renderPass;
435         const Unique<VkPipelineLayout>  m_pipelineLayout;
436         const Unique<VkPipeline>                m_pipeline;
437
438         const Unique<VkBuffer>                  m_vertexBuffer;
439         const UniquePtr<Allocation>             m_vertexBufferMemory;
440
441         vector<ImageViewSp>                             m_attachmentViews;
442         vector<FramebufferSp>                   m_framebuffers;
443 };
444
445 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface&   vkd,
446                                                                                                            const VkDevice                       device,
447                                                                                                            const VkFormat                       colorAttachmentFormat)
448 {
449         const VkAttachmentDescription   colorAttDesc            =
450         {
451                 (VkAttachmentDescriptionFlags)0,
452                 colorAttachmentFormat,
453                 VK_SAMPLE_COUNT_1_BIT,
454                 VK_ATTACHMENT_LOAD_OP_CLEAR,
455                 VK_ATTACHMENT_STORE_OP_STORE,
456                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
457                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
458                 VK_IMAGE_LAYOUT_UNDEFINED,
459                 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
460         };
461         const VkAttachmentReference             colorAttRef                     =
462         {
463                 0u,
464                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
465         };
466         const VkSubpassDescription              subpassDesc                     =
467         {
468                 (VkSubpassDescriptionFlags)0u,
469                 VK_PIPELINE_BIND_POINT_GRAPHICS,
470                 0u,                                                     // inputAttachmentCount
471                 DE_NULL,                                        // pInputAttachments
472                 1u,                                                     // colorAttachmentCount
473                 &colorAttRef,                           // pColorAttachments
474                 DE_NULL,                                        // pResolveAttachments
475                 DE_NULL,                                        // depthStencilAttachment
476                 0u,                                                     // preserveAttachmentCount
477                 DE_NULL,                                        // pPreserveAttachments
478         };
479         const VkSubpassDependency               dependencies[]          =
480         {
481                 {
482                         VK_SUBPASS_EXTERNAL,    // srcSubpass
483                         0u,                                             // dstSubpass
484                         VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
485                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
486                         VK_ACCESS_MEMORY_READ_BIT,
487                         (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
488                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
489                         VK_DEPENDENCY_BY_REGION_BIT
490                 },
491                 {
492                         0u,                                             // srcSubpass
493                         VK_SUBPASS_EXTERNAL,    // dstSubpass
494                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
495                         VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
496                         (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
497                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
498                         VK_ACCESS_MEMORY_READ_BIT,
499                         VK_DEPENDENCY_BY_REGION_BIT
500                 },
501         };
502         const VkRenderPassCreateInfo    renderPassParams        =
503         {
504                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
505                 DE_NULL,
506                 (VkRenderPassCreateFlags)0,
507                 1u,
508                 &colorAttDesc,
509                 1u,
510                 &subpassDesc,
511                 DE_LENGTH_OF_ARRAY(dependencies),
512                 dependencies,
513         };
514
515         return vk::createRenderPass(vkd, device, &renderPassParams);
516 }
517
518 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface&   vkd,
519                                                                                                                            const VkDevice                       device)
520 {
521         const VkPushConstantRange                                               pushConstantRange               =
522         {
523                 VK_SHADER_STAGE_VERTEX_BIT,
524                 0u,                                                                                     // offset
525                 (deUint32)sizeof(deUint32),                                     // size
526         };
527         const VkPipelineLayoutCreateInfo                                pipelineLayoutParams    =
528         {
529                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
530                 DE_NULL,
531                 (vk::VkPipelineLayoutCreateFlags)0,
532                 0u,                                                                                     // setLayoutCount
533                 DE_NULL,                                                                        // pSetLayouts
534                 1u,
535                 &pushConstantRange,
536         };
537
538         return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
539 }
540
541 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface&       vkd,
542                                                                                                    const VkDevice                       device,
543                                                                                                    const VkRenderPass           renderPass,
544                                                                                                    const VkPipelineLayout       pipelineLayout,
545                                                                                                    const BinaryCollection&      binaryCollection,
546                                                                                                    const UVec2&                         renderSize)
547 {
548         // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
549         //               and can be deleted immediately following that call.
550         const Unique<VkShaderModule>                                    vertShaderModule                (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
551         const Unique<VkShaderModule>                                    fragShaderModule                (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
552
553         const VkSpecializationInfo                                              emptyShaderSpecParams   =
554         {
555                 0u,                                                                                     // mapEntryCount
556                 DE_NULL,                                                                        // pMap
557                 0,                                                                                      // dataSize
558                 DE_NULL,                                                                        // pData
559         };
560         const VkPipelineShaderStageCreateInfo                   shaderStageParams[]             =
561         {
562                 {
563                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
564                         DE_NULL,
565                         (VkPipelineShaderStageCreateFlags)0,
566                         VK_SHADER_STAGE_VERTEX_BIT,
567                         *vertShaderModule,
568                         "main",
569                         &emptyShaderSpecParams,
570                 },
571                 {
572                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
573                         DE_NULL,
574                         (VkPipelineShaderStageCreateFlags)0,
575                         VK_SHADER_STAGE_FRAGMENT_BIT,
576                         *fragShaderModule,
577                         "main",
578                         &emptyShaderSpecParams,
579                 }
580         };
581         const VkPipelineDepthStencilStateCreateInfo             depthStencilParams              =
582         {
583                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
584                 DE_NULL,
585                 (VkPipelineDepthStencilStateCreateFlags)0,
586                 DE_FALSE,                                                                       // depthTestEnable
587                 DE_FALSE,                                                                       // depthWriteEnable
588                 VK_COMPARE_OP_ALWAYS,                                           // depthCompareOp
589                 DE_FALSE,                                                                       // depthBoundsTestEnable
590                 DE_FALSE,                                                                       // stencilTestEnable
591                 {
592                         VK_STENCIL_OP_KEEP,                                                     // failOp
593                         VK_STENCIL_OP_KEEP,                                                     // passOp
594                         VK_STENCIL_OP_KEEP,                                                     // depthFailOp
595                         VK_COMPARE_OP_ALWAYS,                                           // compareOp
596                         0u,                                                                                     // compareMask
597                         0u,                                                                                     // writeMask
598                         0u,                                                                                     // reference
599                 },                                                                                      // front
600                 {
601                         VK_STENCIL_OP_KEEP,                                                     // failOp
602                         VK_STENCIL_OP_KEEP,                                                     // passOp
603                         VK_STENCIL_OP_KEEP,                                                     // depthFailOp
604                         VK_COMPARE_OP_ALWAYS,                                           // compareOp
605                         0u,                                                                                     // compareMask
606                         0u,                                                                                     // writeMask
607                         0u,                                                                                     // reference
608                 },                                                                                      // back
609                 -1.0f,                                                                          // minDepthBounds
610                 +1.0f,                                                                          // maxDepthBounds
611         };
612         const VkViewport                                                                viewport0                               =
613         {
614                 0.0f,                                                                           // x
615                 0.0f,                                                                           // y
616                 (float)renderSize.x(),                                          // width
617                 (float)renderSize.y(),                                          // height
618                 0.0f,                                                                           // minDepth
619                 1.0f,                                                                           // maxDepth
620         };
621         const VkRect2D                                                                  scissor0                                =
622         {
623                 { 0u, 0u, },                                                            // offset
624                 { renderSize.x(), renderSize.y() },                     // extent
625         };
626         const VkPipelineViewportStateCreateInfo                 viewportParams                  =
627         {
628                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
629                 DE_NULL,
630                 (VkPipelineViewportStateCreateFlags)0,
631                 1u,
632                 &viewport0,
633                 1u,
634                 &scissor0
635         };
636         const VkPipelineMultisampleStateCreateInfo              multisampleParams               =
637         {
638                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
639                 DE_NULL,
640                 (VkPipelineMultisampleStateCreateFlags)0,
641                 VK_SAMPLE_COUNT_1_BIT,                                          // rasterizationSamples
642                 VK_FALSE,                                                                       // sampleShadingEnable
643                 0.0f,                                                                           // minSampleShading
644                 (const VkSampleMask*)DE_NULL,                           // sampleMask
645                 VK_FALSE,                                                                       // alphaToCoverageEnable
646                 VK_FALSE,                                                                       // alphaToOneEnable
647         };
648         const VkPipelineRasterizationStateCreateInfo    rasterParams                    =
649         {
650                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
651                 DE_NULL,
652                 (VkPipelineRasterizationStateCreateFlags)0,
653                 VK_FALSE,                                                                       // depthClampEnable
654                 VK_FALSE,                                                                       // rasterizerDiscardEnable
655                 VK_POLYGON_MODE_FILL,                                           // polygonMode
656                 VK_CULL_MODE_NONE,                                                      // cullMode
657                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                        // frontFace
658                 VK_FALSE,                                                                       // depthBiasEnable
659                 0.0f,                                                                           // depthBiasConstantFactor
660                 0.0f,                                                                           // depthBiasClamp
661                 0.0f,                                                                           // depthBiasSlopeFactor
662                 1.0f,                                                                           // lineWidth
663         };
664         const VkPipelineInputAssemblyStateCreateInfo    inputAssemblyParams             =
665         {
666                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
667                 DE_NULL,
668                 (VkPipelineInputAssemblyStateCreateFlags)0,
669                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
670                 DE_FALSE,                                                                       // primitiveRestartEnable
671         };
672         const VkVertexInputBindingDescription                   vertexBinding0                  =
673         {
674                 0u,                                                                                     // binding
675                 (deUint32)sizeof(tcu::Vec4),                            // stride
676                 VK_VERTEX_INPUT_RATE_VERTEX,                            // inputRate
677         };
678         const VkVertexInputAttributeDescription                 vertexAttrib0                   =
679         {
680                 0u,                                                                                     // location
681                 0u,                                                                                     // binding
682                 VK_FORMAT_R32G32B32A32_SFLOAT,                          // format
683                 0u,                                                                                     // offset
684         };
685         const VkPipelineVertexInputStateCreateInfo              vertexInputStateParams  =
686         {
687                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
688                 DE_NULL,
689                 (VkPipelineVertexInputStateCreateFlags)0,
690                 1u,
691                 &vertexBinding0,
692                 1u,
693                 &vertexAttrib0,
694         };
695         const VkPipelineColorBlendAttachmentState               attBlendParams0                 =
696         {
697                 VK_FALSE,                                                                       // blendEnable
698                 VK_BLEND_FACTOR_ONE,                                            // srcColorBlendFactor
699                 VK_BLEND_FACTOR_ZERO,                                           // dstColorBlendFactor
700                 VK_BLEND_OP_ADD,                                                        // colorBlendOp
701                 VK_BLEND_FACTOR_ONE,                                            // srcAlphaBlendFactor
702                 VK_BLEND_FACTOR_ZERO,                                           // dstAlphaBlendFactor
703                 VK_BLEND_OP_ADD,                                                        // alphaBlendOp
704                 (VK_COLOR_COMPONENT_R_BIT|
705                  VK_COLOR_COMPONENT_G_BIT|
706                  VK_COLOR_COMPONENT_B_BIT|
707                  VK_COLOR_COMPONENT_A_BIT),                                     // colorWriteMask
708         };
709         const VkPipelineColorBlendStateCreateInfo               blendParams                             =
710         {
711                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
712                 DE_NULL,
713                 (VkPipelineColorBlendStateCreateFlags)0,
714                 VK_FALSE,                                                                       // logicOpEnable
715                 VK_LOGIC_OP_COPY,
716                 1u,
717                 &attBlendParams0,
718                 { 0.0f, 0.0f, 0.0f, 0.0f },                                     // blendConstants[4]
719         };
720         const VkGraphicsPipelineCreateInfo                              pipelineParams                  =
721         {
722                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
723                 DE_NULL,
724                 (VkPipelineCreateFlags)0,
725                 (deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams),
726                 shaderStageParams,
727                 &vertexInputStateParams,
728                 &inputAssemblyParams,
729                 (const VkPipelineTessellationStateCreateInfo*)DE_NULL,
730                 &viewportParams,
731                 &rasterParams,
732                 &multisampleParams,
733                 &depthStencilParams,
734                 &blendParams,
735                 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
736                 pipelineLayout,
737                 renderPass,
738                 0u,                                                                                     // subpass
739                 DE_NULL,                                                                        // basePipelineHandle
740                 0u,                                                                                     // basePipelineIndex
741         };
742
743         return vk::createGraphicsPipeline(vkd, device, (VkPipelineCache)0, &pipelineParams);
744 }
745
746 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface&        vkd,
747                                                                                                                   const VkDevice                        device,
748                                                                                                                   const VkImage                         image,
749                                                                                                                   const VkFormat                        format)
750 {
751         const VkImageViewCreateInfo             viewParams      =
752         {
753                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
754                 DE_NULL,
755                 (VkImageViewCreateFlags)0,
756                 image,
757                 VK_IMAGE_VIEW_TYPE_2D,
758                 format,
759                 vk::makeComponentMappingRGBA(),
760                 {
761                         VK_IMAGE_ASPECT_COLOR_BIT,
762                         0u,                                             // baseMipLevel
763                         1u,                                             // levelCount
764                         0u,                                             // baseArrayLayer
765                         1u,                                             // layerCount
766                 },
767         };
768
769         return vk::createImageView(vkd, device, &viewParams);
770 }
771
772 Move<VkFramebuffer> TriangleRenderer::createFramebuffer (const DeviceInterface&         vkd,
773                                                                                                                  const VkDevice                         device,
774                                                                                                                  const VkRenderPass                     renderPass,
775                                                                                                                  const VkImageView                      colorAttachment,
776                                                                                                                  const UVec2&                           renderSize)
777 {
778         const VkFramebufferCreateInfo   framebufferParams       =
779         {
780                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
781                 DE_NULL,
782                 (VkFramebufferCreateFlags)0,
783                 renderPass,
784                 1u,
785                 &colorAttachment,
786                 renderSize.x(),
787                 renderSize.y(),
788                 1u,                                                     // layers
789         };
790
791         return vk::createFramebuffer(vkd, device, &framebufferParams);
792 }
793
794 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface&   vkd,
795                                                                                            VkDevice                                     device,
796                                                                                            VkDeviceSize                         size,
797                                                                                            VkBufferUsageFlags           usage)
798 {
799         const VkBufferCreateInfo        bufferParams    =
800         {
801                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
802                 DE_NULL,
803                 (VkBufferCreateFlags)0,
804                 size,
805                 usage,
806                 VK_SHARING_MODE_EXCLUSIVE,
807                 0,
808                 DE_NULL
809         };
810
811         return vk::createBuffer(vkd, device, &bufferParams);
812 }
813
814 TriangleRenderer::TriangleRenderer (const DeviceInterface&      vkd,
815                                                                         const VkDevice                  device,
816                                                                         Allocator&                              allocator,
817                                                                         const BinaryCollection& binaryRegistry,
818                                                                         const vector<VkImage>   swapchainImages,
819                                                                         const VkFormat                  framebufferFormat,
820                                                                         const UVec2&                    renderSize)
821         : m_vkd                                 (vkd)
822         , m_swapchainImages             (swapchainImages)
823         , m_renderSize                  (renderSize)
824         , m_renderPass                  (createRenderPass(vkd, device, framebufferFormat))
825         , m_pipelineLayout              (createPipelineLayout(vkd, device))
826         , m_pipeline                    (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
827         , m_vertexBuffer                (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
828         , m_vertexBufferMemory  (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
829                                                          MemoryRequirement::HostVisible))
830 {
831         m_attachmentViews.resize(swapchainImages.size());
832         m_framebuffers.resize(swapchainImages.size());
833
834         for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
835         {
836                 m_attachmentViews[imageNdx]     = ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
837                 m_framebuffers[imageNdx]        = FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
838         }
839
840         VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
841
842         {
843                 const VkMappedMemoryRange       memRange        =
844                 {
845                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
846                         DE_NULL,
847                         m_vertexBufferMemory->getMemory(),
848                         m_vertexBufferMemory->getOffset(),
849                         VK_WHOLE_SIZE
850                 };
851                 const tcu::Vec4                         vertices[]      =
852                 {
853                         tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
854                         tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
855                         tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
856                 };
857                 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
858
859                 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
860                 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
861         }
862 }
863
864 TriangleRenderer::~TriangleRenderer (void)
865 {
866 }
867
868 void TriangleRenderer::recordFrame (VkCommandBuffer     cmdBuffer,
869                                                                         deUint32                imageNdx,
870                                                                         deUint32                frameNdx) const
871 {
872         const VkFramebuffer     curFramebuffer  = **m_framebuffers[imageNdx];
873
874         {
875                 const VkCommandBufferBeginInfo  cmdBufBeginParams       =
876                 {
877                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
878                         DE_NULL,
879                         (VkCommandBufferUsageFlags)0,
880                         (const VkCommandBufferInheritanceInfo*)DE_NULL,
881                 };
882                 VK_CHECK(m_vkd.beginCommandBuffer(cmdBuffer, &cmdBufBeginParams));
883         }
884
885         {
886                 const VkClearValue                      clearValue              = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
887                 const VkRenderPassBeginInfo     passBeginParams =
888                 {
889                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
890                         DE_NULL,
891                         *m_renderPass,
892                         curFramebuffer,
893                         {
894                                 { 0, 0 },
895                                 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
896                         },                                                                                                      // renderArea
897                         1u,                                                                                                     // clearValueCount
898                         &clearValue,                                                                            // pClearValues
899                 };
900                 m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
901         }
902
903         m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
904
905         {
906                 const VkDeviceSize bindingOffset = 0;
907                 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
908         }
909
910         m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
911         m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
912         m_vkd.cmdEndRenderPass(cmdBuffer);
913
914         VK_CHECK(m_vkd.endCommandBuffer(cmdBuffer));
915 }
916
917 void TriangleRenderer::getPrograms (SourceCollections& dst)
918 {
919         dst.glslSources.add("tri-vert") << glu::VertexSource(
920                 "#version 310 es\n"
921                 "layout(location = 0) in highp vec4 a_position;\n"
922                 "layout(push_constant) uniform FrameData\n"
923                 "{\n"
924                 "    highp uint frameNdx;\n"
925                 "} frameData;\n"
926                 "void main (void)\n"
927                 "{\n"
928                 "    highp float angle = float(frameData.frameNdx) / 100.0;\n"
929                 "    highp float c     = cos(angle);\n"
930                 "    highp float s     = sin(angle);\n"
931                 "    highp mat4  t     = mat4( c, -s,  0,  0,\n"
932                 "                              s,  c,  0,  0,\n"
933                 "                              0,  0,  1,  0,\n"
934                 "                              0,  0,  0,  1);\n"
935                 "    gl_Position = t * a_position;\n"
936                 "}\n");
937         dst.glslSources.add("tri-frag") << glu::FragmentSource(
938                 "#version 310 es\n"
939                 "layout(location = 0) out lowp vec4 o_color;\n"
940                 "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
941 }
942
943 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
944 typedef de::SharedPtr<Unique<VkFence> >                 FenceSp;
945 typedef de::SharedPtr<Unique<VkSemaphore> >             SemaphoreSp;
946
947 vector<FenceSp> createFences (const DeviceInterface&    vkd,
948                                                           const VkDevice                        device,
949                                                           size_t                                        numFences)
950 {
951         vector<FenceSp> fences(numFences);
952
953         for (size_t ndx = 0; ndx < numFences; ++ndx)
954                 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
955
956         return fences;
957 }
958
959 vector<SemaphoreSp> createSemaphores (const DeviceInterface&    vkd,
960                                                                           const VkDevice                        device,
961                                                                           size_t                                        numSemaphores)
962 {
963         vector<SemaphoreSp> semaphores(numSemaphores);
964
965         for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
966                 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
967
968         return semaphores;
969 }
970
971 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface&          vkd,
972                                                                                                 const VkDevice                          device,
973                                                                                                 const VkCommandPool                     commandPool,
974                                                                                                 const VkCommandBufferLevel      level,
975                                                                                                 const size_t                            numCommandBuffers)
976 {
977         vector<CommandBufferSp>                         buffers         (numCommandBuffers);
978
979         for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
980                 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
981
982         return buffers;
983 }
984
985 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
986 {
987         const tcu::UVec2                                desiredSize             (256, 256);
988         const InstanceHelper                    instHelper              (context, wsiType);
989         const NativeObjects                             native                  (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
990         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
991         const DeviceHelper                              devHelper               (context, instHelper.vki, *instHelper.instance, *surface);
992
993         if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
994                 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
995
996         const vector<VkSurfaceFormatKHR>        formats                 = getPhysicalDeviceSurfaceFormats(instHelper.vki,
997                                                                                                                                                                                   devHelper.physicalDevice,
998                                                                                                                                                                                   *surface);
999
1000         bool found = false;
1001         for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1002         {
1003                 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
1004                 {
1005                         found = true;
1006                         break;
1007                 }
1008         }
1009         if (!found)
1010         {
1011                 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
1012         }
1013         return tcu::TestStatus::pass("Extension tests succeeded");
1014 }
1015
1016 tcu::TestStatus surfaceFormatRenderTest (Context& context, Type wsiType, VkSurfaceKHR surface, VkSurfaceFormatKHR curFmt)
1017 {
1018         const tcu::UVec2                                        desiredSize             (256, 256);
1019         const InstanceHelper                            instHelper              (context, wsiType);
1020         const DeviceHelper                                      devHelper               (context, instHelper.vki, *instHelper.instance, surface);
1021         const DeviceInterface&                          vkd                             = devHelper.vkd;
1022         const VkDevice                                          device                  = *devHelper.device;
1023         SimpleAllocator                                         allocator               (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
1024
1025         tcu::print("Test Surface format: %s, %s\n", de::toString(curFmt.format).c_str(), de::toString(curFmt.colorSpace).c_str());
1026         const VkSwapchainCreateInfoKHR  swapchainInfo                           = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
1027         const Unique<VkSwapchainKHR>    swapchain                                       (createSwapchainKHR(vkd, device, &swapchainInfo));
1028         const vector<VkImage>                   swapchainImages                         = getSwapchainImages(vkd, device, *swapchain);
1029
1030         const TriangleRenderer                  renderer                                        (vkd,
1031                                                                                                                                  device,
1032                                                                                                                                  allocator,
1033                                                                                                                                  context.getBinaryCollection(),
1034                                                                                                                                  swapchainImages,
1035                                                                                                                                  swapchainInfo.imageFormat,
1036                                                                                                                                  tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
1037
1038         const Unique<VkCommandPool>             commandPool                                     (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
1039
1040         const size_t                                    maxQueuedFrames                         = swapchainImages.size()*2;
1041
1042         // We need to keep hold of fences from vkAcquireNextImageKHR to actually
1043         // limit number of frames we allow to be queued.
1044         const vector<FenceSp>                   imageReadyFences                        (createFences(vkd, device, maxQueuedFrames));
1045
1046         // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
1047         // the semaphore in same time as the fence we use to meter rendering.
1048         const vector<SemaphoreSp>               imageReadySemaphores            (createSemaphores(vkd, device, maxQueuedFrames+1));
1049
1050         // For rest we simply need maxQueuedFrames as we will wait for image
1051         // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
1052         // previous uses must have completed.
1053         const vector<SemaphoreSp>               renderingCompleteSemaphores     (createSemaphores(vkd, device, maxQueuedFrames));
1054         const vector<CommandBufferSp>   commandBuffers                          (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
1055
1056         try
1057         {
1058                 const deUint32  numFramesToRender       = 60;
1059
1060                 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
1061                 {
1062                         const VkFence           imageReadyFence         = **imageReadyFences[frameNdx%imageReadyFences.size()];
1063                         const VkSemaphore       imageReadySemaphore     = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
1064                         deUint32                        imageNdx                        = ~0u;
1065
1066                         if (frameNdx >= maxQueuedFrames)
1067                                 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1068
1069                         VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
1070
1071                         {
1072                                 const VkResult  acquireResult   = vkd.acquireNextImageKHR(device,
1073                                                                                                                                                   *swapchain,
1074                                                                                                                                                   std::numeric_limits<deUint64>::max(),
1075                                                                                                                                                   imageReadySemaphore,
1076                                                                                                                                                   (vk::VkFence)0,
1077                                                                                                                                                   &imageNdx);
1078
1079                                 if (acquireResult == VK_SUBOPTIMAL_KHR)
1080                                         context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1081                                 else
1082                                         VK_CHECK(acquireResult);
1083                         }
1084
1085                         TCU_CHECK((size_t)imageNdx < swapchainImages.size());
1086
1087                         {
1088                                 const VkSemaphore                       renderingCompleteSemaphore      = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
1089                                 const VkCommandBuffer           commandBuffer                           = **commandBuffers[frameNdx%commandBuffers.size()];
1090                                 const VkPipelineStageFlags      waitDstStage                            = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1091                                 const VkSubmitInfo                      submitInfo                                      =
1092                                 {
1093                                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
1094                                         DE_NULL,
1095                                         1u,
1096                                         &imageReadySemaphore,
1097                                         &waitDstStage,
1098                                         1u,
1099                                         &commandBuffer,
1100                                         1u,
1101                                         &renderingCompleteSemaphore
1102                                 };
1103                                 const VkPresentInfoKHR          presentInfo                                     =
1104                                 {
1105                                         VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1106                                         DE_NULL,
1107                                         1u,
1108                                         &renderingCompleteSemaphore,
1109                                         1u,
1110                                         &*swapchain,
1111                                         &imageNdx,
1112                                         (VkResult*)DE_NULL
1113                                 };
1114
1115                                 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
1116                                 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
1117                                 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
1118                         }
1119                 }
1120
1121                 VK_CHECK(vkd.deviceWaitIdle(device));
1122         }
1123         catch (...)
1124         {
1125                 // Make sure device is idle before destroying resources
1126                 vkd.deviceWaitIdle(device);
1127                 throw;
1128         }
1129         tcu::print("Done\n");
1130
1131         return tcu::TestStatus::pass("Rendering test succeeded");
1132 }
1133
1134 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
1135 {
1136         const tcu::UVec2                                        desiredSize             (256, 256);
1137         const InstanceHelper                            instHelper              (context, wsiType);
1138         const NativeObjects                                     native                  (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
1139         const Unique<VkSurfaceKHR>                      surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
1140         const DeviceHelper                                      devHelper               (context, instHelper.vki, *instHelper.instance, *surface);
1141
1142         if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
1143                 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
1144
1145         const vector<VkSurfaceFormatKHR>        formats                 = getPhysicalDeviceSurfaceFormats(instHelper.vki,
1146                                                                                                                                                                                   devHelper.physicalDevice,
1147                                                                                                                                                                                   *surface);
1148         for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1149         {
1150                 surfaceFormatRenderTest(context, wsiType, *surface, *curFmt);
1151         }
1152         return tcu::TestStatus::pass("Rendering tests succeeded");
1153 }
1154
1155 void getBasicRenderPrograms (SourceCollections& dst, Type)
1156 {
1157         TriangleRenderer::getPrograms(dst);
1158 }
1159
1160 } // anonymous
1161
1162 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1163 {
1164         addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
1165         addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
1166 }
1167
1168 } // wsi
1169 } // vkt