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