Test behaviour of color write enable with colorWriteMask
[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 #include "vktCustomInstancesDevices.hpp"
29
30 #include "vkDefs.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkStrUtil.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkDeviceUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkWsiPlatform.hpp"
42 #include "vkWsiUtil.hpp"
43 #include "vkAllocationCallbackUtil.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkObjUtil.hpp"
46 #include "tcuSurface.hpp"
47 #include "vkImageUtil.hpp"
48
49 #include "tcuTestLog.hpp"
50 #include "tcuFormatUtil.hpp"
51 #include "tcuPlatform.hpp"
52 #include "tcuResultCollector.hpp"
53 #include "tcuCommandLine.hpp"
54
55 #include "deUniquePtr.hpp"
56 #include "deStringUtil.hpp"
57 #include "deArrayUtil.hpp"
58 #include "deSharedPtr.hpp"
59
60 #include <limits>
61
62 namespace vkt
63 {
64 namespace wsi
65 {
66
67 namespace
68 {
69
70 using namespace vk;
71 using namespace vk::wsi;
72
73 using tcu::TestLog;
74 using tcu::Maybe;
75 using tcu::UVec2;
76
77 using de::MovePtr;
78 using de::UniquePtr;
79
80 using std::string;
81 using std::vector;
82
83 typedef vector<VkExtensionProperties> Extensions;
84
85 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
86 {
87         for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
88                  requiredExtName != requiredExtensions.end();
89                  ++requiredExtName)
90         {
91                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
92                         TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
93         }
94 }
95
96 CustomInstance createInstanceWithWsi (Context&                                          context,
97                                                                           const Extensions&                             supportedExtensions,
98                                                                           Type                                                  wsiType,
99                                                                           const VkAllocationCallbacks*  pAllocator      = DE_NULL)
100 {
101         vector<string>  extensions;
102
103         extensions.push_back("VK_KHR_surface");
104         extensions.push_back(getExtensionName(wsiType));
105
106         // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
107         // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
108         // but using them without enabling the extension is not allowed. Thus we have
109         // two options:
110         //
111         // 1) Filter out non-core formats to stay within valid usage.
112         //
113         // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
114         //
115         // We opt for (2) as it provides basic coverage for the extension as a bonus.
116         if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
117                 extensions.push_back("VK_EXT_swapchain_colorspace");
118
119         checkAllSupported(supportedExtensions, extensions);
120
121         return createCustomInstanceWithExtensions(context, extensions, pAllocator);
122 }
123
124 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
125 {
126         VkPhysicalDeviceFeatures features;
127         deMemset(&features, 0, sizeof(features));
128         return features;
129 }
130
131 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface&        vkp,
132                                                                         vk::VkInstance                                  instance,
133                                                                         const InstanceInterface&                vki,
134                                                                         VkPhysicalDevice                                physicalDevice,
135                                                                         const Extensions&                               supportedExtensions,
136                                                                         const deUint32                                  queueFamilyIndex,
137                                                                         const VkAllocationCallbacks*    pAllocator,
138                                                                         bool                                                    validationEnabled)
139 {
140         const float                                             queuePriorities[]       = { 1.0f };
141         const VkDeviceQueueCreateInfo   queueInfos[]            =
142         {
143                 {
144                         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
145                         DE_NULL,
146                         (VkDeviceQueueCreateFlags)0,
147                         queueFamilyIndex,
148                         DE_LENGTH_OF_ARRAY(queuePriorities),
149                         &queuePriorities[0]
150                 }
151         };
152         const VkPhysicalDeviceFeatures  features                = getDeviceFeaturesForWsi();
153         vector<const char*>             extensions;
154
155         if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
156                 TCU_THROW(NotSupportedError, "VK_KHR_swapchain is not supported");
157         extensions.push_back("VK_KHR_swapchain");
158
159         if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
160                 extensions.push_back("VK_EXT_hdr_metadata");
161
162         VkDeviceCreateInfo              deviceParams    =
163         {
164                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
165                 DE_NULL,
166                 (VkDeviceCreateFlags)0,
167                 DE_LENGTH_OF_ARRAY(queueInfos),
168                 &queueInfos[0],
169                 0u,                                                                     // enabledLayerCount
170                 DE_NULL,                                                        // ppEnabledLayerNames
171                 (deUint32)extensions.size(),
172                 extensions.empty() ? DE_NULL : &extensions[0],
173                 &features
174         };
175
176         return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
177 }
178
179 struct InstanceHelper
180 {
181         const vector<VkExtensionProperties>     supportedExtensions;
182         const CustomInstance                            instance;
183         const InstanceDriver&                           vki;
184
185         InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
186                 : supportedExtensions   (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
187                                                                                                                                           DE_NULL))
188                 , instance                              (createInstanceWithWsi(context,
189                                                                                                            supportedExtensions,
190                                                                                                            wsiType,
191                                                                                                            pAllocator))
192                 , vki                                   (instance.getDriver())
193         {}
194 };
195
196 struct DeviceHelper
197 {
198         const VkPhysicalDevice  physicalDevice;
199         const deUint32                  queueFamilyIndex;
200         const Unique<VkDevice>  device;
201         const DeviceDriver              vkd;
202         const VkQueue                   queue;
203
204         DeviceHelper (Context&                                          context,
205                                   const InstanceInterface&              vki,
206                                   VkInstance                                    instance,
207                                   VkSurfaceKHR                                  surface,
208                                   const VkAllocationCallbacks*  pAllocator = DE_NULL)
209                 : physicalDevice        (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
210                 , queueFamilyIndex      (chooseQueueFamilyIndex(vki, physicalDevice, surface))
211                 , device                        (createDeviceWithWsi(context.getPlatformInterface(),
212                                                                                                  instance,
213                                                                                                  vki,
214                                                                                                  physicalDevice,
215                                                                                                  enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
216                                                                                                  queueFamilyIndex,
217                                                                                                  pAllocator,
218                                                                                                  context.getTestContext().getCommandLine().isValidationEnabled()))
219                 , vkd                           (context.getPlatformInterface(), instance, *device)
220                 , queue                         (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
221         {
222         }
223 };
224
225 MovePtr<Display> createDisplay (const vk::Platform&     platform,
226                                                                 const Extensions&       supportedExtensions,
227                                                                 Type                            wsiType)
228 {
229         try
230         {
231                 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
232         }
233         catch (const tcu::NotSupportedError& e)
234         {
235                 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
236                     platform.hasDisplay(wsiType))
237                 {
238                         // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
239                         // must support creating native display & window for that WSI type.
240                         throw tcu::TestError(e.getMessage());
241                 }
242                 else
243                         throw;
244         }
245 }
246
247 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
248 {
249         try
250         {
251                 return MovePtr<Window>(display.createWindow(initialSize));
252         }
253         catch (const tcu::NotSupportedError& e)
254         {
255                 // See createDisplay - assuming that wsi::Display was supported platform port
256                 // should also support creating a window.
257                 throw tcu::TestError(e.getMessage());
258         }
259 }
260
261 struct NativeObjects
262 {
263         const UniquePtr<Display>        display;
264         const UniquePtr<Window>         window;
265
266         NativeObjects (Context&                         context,
267                                    const Extensions&    supportedExtensions,
268                                    Type                                 wsiType,
269                                    const Maybe<UVec2>&  initialWindowSize = tcu::nothing<UVec2>())
270                 : display       (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
271                 , window        (createWindow(*display, initialWindowSize))
272         {}
273 };
274
275 enum TestDimension
276 {
277         TEST_DIMENSION_MIN_IMAGE_COUNT = 0,     //!< Test all supported image counts
278         TEST_DIMENSION_IMAGE_FORMAT,            //!< Test all supported formats
279         TEST_DIMENSION_IMAGE_EXTENT,            //!< Test various (supported) extents
280         TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
281         TEST_DIMENSION_IMAGE_USAGE,
282         TEST_DIMENSION_IMAGE_SHARING_MODE,
283         TEST_DIMENSION_PRE_TRANSFORM,
284         TEST_DIMENSION_COMPOSITE_ALPHA,
285         TEST_DIMENSION_PRESENT_MODE,
286         TEST_DIMENSION_CLIPPED,
287
288         TEST_DIMENSION_LAST
289 };
290
291 struct TestParameters
292 {
293         Type                    wsiType;
294         TestDimension   dimension;
295
296         TestParameters (Type wsiType_, TestDimension dimension_)
297                 : wsiType       (wsiType_)
298                 , dimension     (dimension_)
299         {}
300
301         TestParameters (void)
302                 : wsiType       (TYPE_LAST)
303                 , dimension     (TEST_DIMENSION_LAST)
304         {}
305 };
306
307 struct GroupParameters
308 {
309         typedef FunctionInstance1<TestParameters>::Function     Function;
310
311         Type            wsiType;
312         Function        function;
313
314         GroupParameters (Type wsiType_, Function function_)
315                 : wsiType       (wsiType_)
316                 , function      (function_)
317         {}
318
319         GroupParameters (void)
320                 : wsiType       (TYPE_LAST)
321                 , function      ((Function)DE_NULL)
322         {}
323 };
324
325 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type                                              wsiType,
326                                                                                                           const InstanceInterface&      vki,
327                                                                                                           VkPhysicalDevice                      physicalDevice,
328                                                                                                           VkSurfaceKHR                          surface,
329                                                                                                           VkSurfaceFormatKHR            surfaceFormat,
330                                                                                                           const tcu::UVec2&                     desiredSize,
331                                                                                                           deUint32                                      desiredImageCount,
332                                                                                                           VkColorSpaceKHR                       desiredColorspace = VK_COLOR_SPACE_MAX_ENUM_KHR)
333 {
334         bool setColorspaceManually = desiredColorspace != VK_COLOR_SPACE_MAX_ENUM_KHR;
335
336         const VkSurfaceCapabilitiesKHR          capabilities            = getPhysicalDeviceSurfaceCapabilities(vki,
337                                                                                                                                                                                                    physicalDevice,
338                                                                                                                                                                                                    surface);
339         const PlatformProperties&                       platformProperties      = getPlatformProperties(wsiType);
340         const VkSurfaceCapabilitiesKHR          surfaceCapabilities     = getPhysicalDeviceSurfaceCapabilities(vki,physicalDevice, surface);
341
342         // Check that the device has at least one supported alpha compositing mode
343         // and pick the first supported mode to be used.
344         vk::VkCompositeAlphaFlagsKHR            alpha                           = 0;
345         for (deUint32 i = 1u; i <= surfaceCapabilities.supportedCompositeAlpha; i <<= 1u)
346         {
347                 if ((i & surfaceCapabilities.supportedCompositeAlpha) != 0)
348                 {
349                         alpha = i;
350                         break;
351                 }
352         }
353         if (alpha == 0)
354                 TCU_THROW(NotSupportedError, "No supported composite alphas available.");
355
356         const VkSurfaceTransformFlagBitsKHR transform                   = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
357         const VkSwapchainCreateInfoKHR          parameters                      =
358         {
359                 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
360                 DE_NULL,
361                 (VkSwapchainCreateFlagsKHR)0,
362                 surface,
363                 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
364                 surfaceFormat.format,
365                 (setColorspaceManually ? desiredColorspace : surfaceFormat.colorSpace),
366                 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
367                 1u,                                                                     // imageArrayLayers
368                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
369                 VK_SHARING_MODE_EXCLUSIVE,
370                 0u,
371                 (const deUint32*)DE_NULL,
372                 transform,
373                 static_cast<VkCompositeAlphaFlagBitsKHR>(alpha),
374                 VK_PRESENT_MODE_FIFO_KHR,
375                 VK_FALSE,                                                       // clipped
376                 (VkSwapchainKHR)0                                       // oldSwapchain
377         };
378
379         return parameters;
380 }
381
382 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
383 typedef de::SharedPtr<Unique<VkFence> >                 FenceSp;
384 typedef de::SharedPtr<Unique<VkSemaphore> >             SemaphoreSp;
385
386 vector<FenceSp> createFences (const DeviceInterface&    vkd,
387                                                           const VkDevice                        device,
388                                                           size_t                                        numFences)
389 {
390         vector<FenceSp> fences(numFences);
391
392         for (size_t ndx = 0; ndx < numFences; ++ndx)
393                 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
394
395         return fences;
396 }
397
398 vector<SemaphoreSp> createSemaphores (const DeviceInterface&    vkd,
399                                                                           const VkDevice                        device,
400                                                                           size_t                                        numSemaphores)
401 {
402         vector<SemaphoreSp> semaphores(numSemaphores);
403
404         for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
405                 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
406
407         return semaphores;
408 }
409
410 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface&          vkd,
411                                                                                                 const VkDevice                          device,
412                                                                                                 const VkCommandPool                     commandPool,
413                                                                                                 const VkCommandBufferLevel      level,
414                                                                                                 const size_t                            numCommandBuffers)
415 {
416         vector<CommandBufferSp>                         buffers         (numCommandBuffers);
417
418         for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
419                 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
420
421         return buffers;
422 }
423
424 tcu::Vec4 getPixel (const DeviceInterface&              vkd,
425                                         const VkDevice                          device,
426                                         const VkQueue                           queue,
427                                         const VkCommandPool&            commandPool,
428                                         Allocator&                                      allocator,
429                                         const tcu::UVec2                        size,
430                                         const tcu::TextureFormat        textureFormat,
431                                         const VkImage*                          image)
432 {
433         Move<VkCommandBuffer>           commandBuffer;
434         Move<VkBuffer>                          resultBuffer;
435         de::MovePtr<Allocation>         resultBufferMemory;
436
437         commandBuffer = allocateCommandBuffer(vkd, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
438
439         // Result Buffer
440         {
441                 const VkDeviceSize                      bufferSize = textureFormat.getPixelSize() * size.x() * size.y();
442                 const VkBufferCreateInfo        createInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
443
444                 resultBuffer                            = createBuffer(vkd, device, &createInfo);
445                 resultBufferMemory                      = allocator.allocate(getBufferMemoryRequirements(vkd, device, *resultBuffer), MemoryRequirement::HostVisible);
446
447                 VK_CHECK(vkd.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
448         }
449
450         beginCommandBuffer(vkd, *commandBuffer, 0u);
451         {
452                 copyImageToBuffer(vkd, *commandBuffer, *image, *resultBuffer, tcu::IVec2(size.x(), size.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
453         }
454         endCommandBuffer(vkd, *commandBuffer);
455         submitCommandsAndWait(vkd, device, queue, commandBuffer.get());
456
457         tcu::ConstPixelBufferAccess     resultAccess(textureFormat,
458                                                                                          tcu::IVec3(size.x(), size.y(), 1),
459                                                                                          resultBufferMemory->getHostPtr());
460
461         return (resultAccess.getPixel(128, 128));
462 }
463
464 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
465 {
466         const tcu::UVec2                                desiredSize             (256, 256);
467         const InstanceHelper                    instHelper              (context, wsiType);
468         const NativeObjects                             native                  (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
469         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
470         const DeviceHelper                              devHelper               (context, instHelper.vki, instHelper.instance, *surface);
471
472         if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
473                 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
474
475         const vector<VkSurfaceFormatKHR>        formats                 = getPhysicalDeviceSurfaceFormats(instHelper.vki,
476                                                                                                                                                                                   devHelper.physicalDevice,
477                                                                                                                                                                                   *surface);
478
479         bool found = false;
480         for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
481         {
482                 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
483                 {
484                         found = true;
485                         break;
486                 }
487         }
488         if (!found)
489         {
490                 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
491         }
492         return tcu::TestStatus::pass("Extension tests succeeded");
493 }
494
495 struct TestParams
496 {
497         Type            wsiType;
498         VkFormat        format;
499 };
500
501 // Create swapchain with multiple images on different colorspaces and compare pixels on those images.
502 tcu::TestStatus colorspaceCompareTest (Context& context, TestParams params)
503 {
504         if (!context.isInstanceFunctionalitySupported("VK_EXT_swapchain_colorspace"))
505                 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
506
507         const tcu::UVec2                                        desiredSize                             (256, 256);
508         const InstanceHelper                            instHelper                              (context, params.wsiType);
509         const NativeObjects                                     native                                  (context, instHelper.supportedExtensions, params.wsiType, tcu::just(desiredSize));
510         const Unique<VkSurfaceKHR>                      surface                                 (createSurface(instHelper.vki, instHelper.instance, params.wsiType, *native.display, *native.window));
511         const DeviceHelper                                      devHelper                               (context, instHelper.vki, instHelper.instance, *surface);
512
513         const vector<VkSurfaceFormatKHR>        queriedFormats          =       getPhysicalDeviceSurfaceFormats(instHelper.vki,
514                                                                                                                                                                                                 devHelper.physicalDevice,
515                                                                                                                                                                                                 *surface);
516
517         vector<vk::VkColorSpaceKHR> supportedColorSpaces;
518         for (const auto& queriedFormat : queriedFormats)
519         {
520                 if (queriedFormat.format == params.format)
521                 {
522                         supportedColorSpaces.push_back(queriedFormat.colorSpace);
523                 }
524         }
525
526         // Not supported if there's no color spaces for the format.
527         if(supportedColorSpaces.size() < 2)
528                 TCU_THROW(NotSupportedError, "Format not supported");
529
530         // Surface format is used to create the swapchain.
531         VkSurfaceFormatKHR surfaceFormat =
532         {
533                 params.format,                          // format
534                 supportedColorSpaces.at(0)      // colorSpace
535         };
536
537         tcu::Vec4                                                referenceColorspacePixel;
538         const tcu::TextureFormat                 textureFormat                          = vk::mapVkFormat(surfaceFormat.format);
539         const DeviceInterface&                   vkd                                            = devHelper.vkd;
540         const VkDevice                                   device                                         = *devHelper.device;
541         SimpleAllocator                                  allocator                                      (vkd,
542                                                                                                                                  device,
543                                                                                                                                  getPhysicalDeviceMemoryProperties(instHelper.vki,
544                                                                                                                                  context.getPhysicalDevice()));
545
546         for (size_t colorspaceNdx = 0; colorspaceNdx < supportedColorSpaces.size(); ++colorspaceNdx)
547         {
548                 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(params.wsiType,
549                                                                                                                                                                    instHelper.vki,
550                                                                                                                                                                    devHelper.physicalDevice,
551                                                                                                                                                                    *surface,
552                                                                                                                                                                    surfaceFormat,
553                                                                                                                                                                    desiredSize,
554                                                                                                                                                                    2,
555                                                                                                                                                                    supportedColorSpaces[colorspaceNdx]);
556                 const Unique<VkSwapchainKHR>            swapchain                       (createSwapchainKHR(vkd, device, &swapchainInfo));
557                 const vector<VkImage>                           swapchainImages         = getSwapchainImages(vkd, device, *swapchain);
558                 const vector<VkExtensionProperties>     deviceExtensions        (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
559
560                 const WsiTriangleRenderer renderer(vkd,
561                                                                                    device,
562                                                                                    allocator,
563                                                                                    context.getBinaryCollection(),
564                                                                                    true,
565                                                                                    swapchainImages,
566                                                                                    swapchainImages,
567                                                                                    swapchainInfo.imageFormat,
568                                                                                    tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
569
570                 const Move<VkCommandPool>       commandPool                                     (createCommandPool(vkd,
571                                                                                                                                                                    device,
572                                                                                                                                                                    VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
573                                                                                                                                                                    devHelper.queueFamilyIndex));
574                 const Move<VkSemaphore>         imageReadySemaphore                     = createSemaphore(vkd, device);
575                 const Move<VkSemaphore>         renderingCompleteSemaphore      = createSemaphore(vkd, device);
576                 const Move<VkCommandBuffer>     commandBuffer                           = allocateCommandBuffer(vkd,
577                                                                                                                                                                                 device,
578                                                                                                                                                                                 *commandPool,
579                                                                                                                                                                                 VK_COMMAND_BUFFER_LEVEL_PRIMARY);
580
581                 try
582                 {
583                         deUint32 imageNdx = ~0u;
584
585                         {
586                                 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
587                                                                                                                                            *swapchain,
588                                                                                                                                            std::numeric_limits<deUint64>::max(),
589                                                                                                                                            imageReadySemaphore.get(),
590                                                                                                                                            DE_NULL,
591                                                                                                                                            &imageNdx);
592
593                                 if (acquireResult == VK_SUBOPTIMAL_KHR)
594                                 {
595                                         context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult
596                                                                                                           << TestLog::EndMessage;
597                                 }
598                                 else
599                                 {
600                                         VK_CHECK(acquireResult);
601                                 }
602                         }
603
604                         TCU_CHECK((size_t) imageNdx < swapchainImages.size());
605
606                         {
607                                 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
608                                 const VkSubmitInfo submitInfo =
609                                 {
610                                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
611                                         DE_NULL,
612                                         0u,
613                                         &imageReadySemaphore.get(),
614                                         &waitDstStage,
615                                         1u,
616                                         &commandBuffer.get(),
617                                         1u,
618                                         &renderingCompleteSemaphore.get()
619                                 };
620                                 const VkPresentInfoKHR presentInfo =
621                                 {
622                                         VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
623                                         DE_NULL,
624                                         1u,
625                                         &renderingCompleteSemaphore.get(),
626                                         1u,
627                                         &swapchain.get(),
628                                         &imageNdx,
629                                         (VkResult *) DE_NULL
630                                 };
631
632                                 renderer.recordFrame(commandBuffer.get(), imageNdx, 0);
633                                 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, DE_NULL));
634                                 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
635                         }
636
637                         // Set reference pixelBufferAccess for comparison.
638                         if (colorspaceNdx == 0)
639                         {
640                                 referenceColorspacePixel = getPixel(vkd, device, devHelper.queue, commandPool.get(),
641                                                                                                         allocator, desiredSize, textureFormat,
642                                                                                                         &swapchainImages[imageNdx]);
643                                 continue;
644                         }
645
646                         // Compare pixels from images to make sure the colorspace makes no difference.
647                         if (referenceColorspacePixel == getPixel(vkd, device, devHelper.queue, commandPool.get(),
648                                                                                                          allocator, desiredSize, textureFormat,
649                                                                                                          &swapchainImages[imageNdx]))
650                                 continue;
651                         else
652                         {
653                                 VK_CHECK(vkd.deviceWaitIdle(device));
654                                 return tcu::TestStatus::fail("Colorspace comparison test failed");
655                         }
656                 }
657                 catch (...)
658                 {
659                         // Make sure device is idle before destroying resources
660                         vkd.deviceWaitIdle(device);
661                         throw;
662                 }
663         }
664
665         VK_CHECK(vkd.deviceWaitIdle(device));
666         return tcu::TestStatus::pass("Colorspace comparison test succeeded");
667 }
668
669 tcu::TestStatus surfaceFormatRenderTest (Context& context,
670                                                                                  Type wsiType,
671                                                                                  const InstanceHelper& instHelper,
672                                                                                  const DeviceHelper& devHelper,
673                                                                                  VkSurfaceKHR surface,
674                                                                                  VkSurfaceFormatKHR curFmt,
675                                                                                  deBool checkHdr = false)
676 {
677         const tcu::UVec2                                        desiredSize             (256, 256);
678         const DeviceInterface&                          vkd                             = devHelper.vkd;
679         const VkDevice                                          device                  = *devHelper.device;
680         SimpleAllocator                                         allocator               (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
681
682         const VkSwapchainCreateInfoKHR          swapchainInfo                   = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
683         const Unique<VkSwapchainKHR>            swapchain                               (createSwapchainKHR(vkd, device, &swapchainInfo));
684         const vector<VkImage>                           swapchainImages                 = getSwapchainImages(vkd, device, *swapchain);
685         const vector<VkExtensionProperties>     deviceExtensions                (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
686
687         if (checkHdr && !isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
688                 TCU_THROW(NotSupportedError, "Extension VK_EXT_hdr_metadata not supported");
689
690         const WsiTriangleRenderer               renderer                                        (vkd,
691                                                                                                                                  device,
692                                                                                                                                  allocator,
693                                                                                                                                  context.getBinaryCollection(),
694                                                                                                                                  true,
695                                                                                                                                  swapchainImages,
696                                                                                                                                  swapchainImages,
697                                                                                                                                  swapchainInfo.imageFormat,
698                                                                                                                                  tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
699
700         const Unique<VkCommandPool>             commandPool                                     (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
701
702         const size_t                                    maxQueuedFrames                         = swapchainImages.size()*2;
703
704         // We need to keep hold of fences from vkAcquireNextImageKHR to actually
705         // limit number of frames we allow to be queued.
706         const vector<FenceSp>                   imageReadyFences                        (createFences(vkd, device, maxQueuedFrames));
707
708         // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
709         // the semaphore in same time as the fence we use to meter rendering.
710         const vector<SemaphoreSp>               imageReadySemaphores            (createSemaphores(vkd, device, maxQueuedFrames+1));
711
712         // For rest we simply need maxQueuedFrames as we will wait for image
713         // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
714         // previous uses must have completed.
715         const vector<SemaphoreSp>               renderingCompleteSemaphores     (createSemaphores(vkd, device, maxQueuedFrames));
716         const vector<CommandBufferSp>   commandBuffers                          (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
717
718         try
719         {
720                 const deUint32  numFramesToRender       = 60;
721
722                 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
723                 {
724                         const VkFence           imageReadyFence         = **imageReadyFences[frameNdx%imageReadyFences.size()];
725                         const VkSemaphore       imageReadySemaphore     = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
726                         deUint32                        imageNdx                        = ~0u;
727
728                         if (frameNdx >= maxQueuedFrames)
729                                 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
730
731                         VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
732
733                         {
734                                 const VkResult  acquireResult   = vkd.acquireNextImageKHR(device,
735                                                                                                                                                   *swapchain,
736                                                                                                                                                   std::numeric_limits<deUint64>::max(),
737                                                                                                                                                   imageReadySemaphore,
738                                                                                                                                                   (vk::VkFence)0,
739                                                                                                                                                   &imageNdx);
740
741                                 if (acquireResult == VK_SUBOPTIMAL_KHR)
742                                         context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
743                                 else
744                                         VK_CHECK(acquireResult);
745                         }
746
747                         TCU_CHECK((size_t)imageNdx < swapchainImages.size());
748
749                         {
750                                 const VkSemaphore                       renderingCompleteSemaphore      = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
751                                 const VkCommandBuffer           commandBuffer                           = **commandBuffers[frameNdx%commandBuffers.size()];
752                                 const VkPipelineStageFlags      waitDstStage                            = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
753                                 const VkSubmitInfo                      submitInfo                                      =
754                                 {
755                                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
756                                         DE_NULL,
757                                         1u,
758                                         &imageReadySemaphore,
759                                         &waitDstStage,
760                                         1u,
761                                         &commandBuffer,
762                                         1u,
763                                         &renderingCompleteSemaphore
764                                 };
765                                 const VkPresentInfoKHR          presentInfo                                     =
766                                 {
767                                         VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
768                                         DE_NULL,
769                                         1u,
770                                         &renderingCompleteSemaphore,
771                                         1u,
772                                         &*swapchain,
773                                         &imageNdx,
774                                         (VkResult*)DE_NULL
775                                 };
776
777                                 if (checkHdr) {
778                                         const VkHdrMetadataEXT hdrData = {
779                                                         VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
780                                                         DE_NULL,
781                                                         makeXYColorEXT(0.680f, 0.320f),
782                                                         makeXYColorEXT(0.265f, 0.690f),
783                                                         makeXYColorEXT(0.150f, 0.060f),
784                                                         makeXYColorEXT(0.3127f, 0.3290f),
785                                                         1000.0,
786                                                         0.0,
787                                                         1000.0,
788                                                         70.0
789                                         };
790                                         vector<VkSwapchainKHR> swapchainArray;
791
792                                         swapchainArray.push_back(*swapchain);
793                                         vkd.setHdrMetadataEXT(device, (deUint32)swapchainArray.size(), swapchainArray.data(), &hdrData);
794                                 }
795
796                                 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
797                                 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
798                                 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
799                         }
800                 }
801
802                 VK_CHECK(vkd.deviceWaitIdle(device));
803         }
804         catch (...)
805         {
806                 // Make sure device is idle before destroying resources
807                 vkd.deviceWaitIdle(device);
808                 throw;
809         }
810
811         return tcu::TestStatus::pass("Rendering test succeeded");
812 }
813
814 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
815 {
816         const tcu::UVec2                                        desiredSize             (256, 256);
817         const InstanceHelper                            instHelper              (context, wsiType);
818         const NativeObjects                                     native                  (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
819         const Unique<VkSurfaceKHR>                      surface                 (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
820         const DeviceHelper                                      devHelper               (context, instHelper.vki, instHelper.instance, *surface);
821
822         if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
823                 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
824
825         const vector<VkSurfaceFormatKHR>        formats                 = getPhysicalDeviceSurfaceFormats(instHelper.vki,
826                                                                                                                                                                                          devHelper.physicalDevice,
827                                                                                                                                                                                          *surface);
828         for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
829         {
830                 surfaceFormatRenderTest(context, wsiType, instHelper, devHelper, *surface, *curFmt);
831         }
832         return tcu::TestStatus::pass("Rendering tests succeeded");
833 }
834
835 tcu::TestStatus surfaceFormatRenderWithHdrTests (Context& context, Type wsiType)
836 {
837         const tcu::UVec2                                        desiredSize             (256, 256);
838         const InstanceHelper                            instHelper              (context, wsiType);
839         const NativeObjects                                     native                  (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
840         const Unique<VkSurfaceKHR>                      surface                 (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
841         const DeviceHelper                                      devHelper               (context, instHelper.vki, instHelper.instance, *surface);
842
843         if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
844                 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
845
846         const vector<VkSurfaceFormatKHR>        formats                 = getPhysicalDeviceSurfaceFormats(instHelper.vki,
847                                                                                                                                                                                   devHelper.physicalDevice,
848                                                                                                                                                                                   *surface);
849         for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
850         {
851                 surfaceFormatRenderTest(context, wsiType, instHelper, devHelper, *surface, *curFmt, true);
852         }
853         return tcu::TestStatus::pass("Rendering tests succeeded");
854 }
855
856 // We need different versions of this function in order to invoke
857 // different overloaded versions of addFunctionCaseWithPrograms.
858 void getBasicRenderPrograms2 (SourceCollections& dst, TestParams)
859 {
860         WsiTriangleRenderer::getPrograms(dst);
861 }
862
863 void getBasicRenderPrograms (SourceCollections& dst, Type)
864 {
865         WsiTriangleRenderer::getPrograms(dst);
866 }
867 } // anonymous
868
869 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
870 {
871         addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
872         addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
873         addFunctionCaseWithPrograms(testGroup, "hdr", "Basic Rendering Tests with HDR", getBasicRenderPrograms, surfaceFormatRenderWithHdrTests, wsiType);
874 }
875
876 void createColorspaceCompareTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
877 {
878         const VkFormat formatList[] = {
879                                                                         VK_FORMAT_B8G8R8A8_UNORM,
880                                                                         VK_FORMAT_R8G8B8A8_UNORM,
881                                                                         VK_FORMAT_R8G8B8A8_SRGB,
882                                                                         VK_FORMAT_R5G6B5_UNORM_PACK16,
883                                                                         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
884                                                                         VK_FORMAT_R16G16B16A16_SFLOAT
885                                                                         };
886
887         // Create test for every format.
888         for (const VkFormat& format : formatList)
889         {
890                 const char* const       enumName        = getFormatName(format);
891                 const string            caseName        = de::toLower(string(enumName).substr(10));
892                 const TestParams params =
893                 {
894                         wsiType,
895                         format
896                 };
897                 addFunctionCaseWithPrograms(testGroup, caseName, "", getBasicRenderPrograms2, colorspaceCompareTest, params);
898         }
899 }
900
901 } // wsi
902 } // vkt