Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineImageSamplingInstance.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Image sampling case
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineImageSamplingInstance.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineReferenceRenderer.hpp"
28 #include "vkBuilderUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkObjUtil.hpp"
37 #include "tcuTexLookupVerifier.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuTestLog.hpp"
40 #include "deSTLUtil.hpp"
41
42 namespace vkt
43 {
44 namespace pipeline
45 {
46
47 using namespace vk;
48 using de::MovePtr;
49 using de::UniquePtr;
50
51 namespace
52 {
53 de::MovePtr<Allocation> allocateBuffer (const InstanceInterface&        vki,
54                                                                                 const DeviceInterface&          vkd,
55                                                                                 const VkPhysicalDevice&         physDevice,
56                                                                                 const VkDevice                          device,
57                                                                                 const VkBuffer&                         buffer,
58                                                                                 const MemoryRequirement         requirement,
59                                                                                 Allocator&                                      allocator,
60                                                                                 AllocationKind                          allocationKind)
61 {
62         switch (allocationKind)
63         {
64                 case ALLOCATION_KIND_SUBALLOCATED:
65                 {
66                         const VkMemoryRequirements      memoryRequirements      = getBufferMemoryRequirements(vkd, device, buffer);
67
68                         return allocator.allocate(memoryRequirements, requirement);
69                 }
70
71                 case ALLOCATION_KIND_DEDICATED:
72                 {
73                         return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
74                 }
75
76                 default:
77                 {
78                         TCU_THROW(InternalError, "Invalid allocation kind");
79                 }
80         }
81 }
82
83 de::MovePtr<Allocation> allocateImage (const InstanceInterface&         vki,
84                                                                            const DeviceInterface&               vkd,
85                                                                            const VkPhysicalDevice&              physDevice,
86                                                                            const VkDevice                               device,
87                                                                            const VkImage&                               image,
88                                                                            const MemoryRequirement              requirement,
89                                                                            Allocator&                                   allocator,
90                                                                            AllocationKind                               allocationKind)
91 {
92         switch (allocationKind)
93         {
94                 case ALLOCATION_KIND_SUBALLOCATED:
95                 {
96                         const VkMemoryRequirements      memoryRequirements      = getImageMemoryRequirements(vkd, device, image);
97
98                         return allocator.allocate(memoryRequirements, requirement);
99                 }
100
101                 case ALLOCATION_KIND_DEDICATED:
102                 {
103                         return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
104                 }
105
106                 default:
107                 {
108                         TCU_THROW(InternalError, "Invalid allocation kind");
109                 }
110         }
111 }
112
113 static VkImageType getCompatibleImageType (VkImageViewType viewType)
114 {
115         switch (viewType)
116         {
117                 case VK_IMAGE_VIEW_TYPE_1D:                             return VK_IMAGE_TYPE_1D;
118                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:               return VK_IMAGE_TYPE_1D;
119                 case VK_IMAGE_VIEW_TYPE_2D:                             return VK_IMAGE_TYPE_2D;
120                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:               return VK_IMAGE_TYPE_2D;
121                 case VK_IMAGE_VIEW_TYPE_3D:                             return VK_IMAGE_TYPE_3D;
122                 case VK_IMAGE_VIEW_TYPE_CUBE:                   return VK_IMAGE_TYPE_2D;
123                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:             return VK_IMAGE_TYPE_2D;
124                 default:
125                         break;
126         }
127
128         DE_ASSERT(false);
129         return VK_IMAGE_TYPE_1D;
130 }
131
132 template<typename TcuFormatType>
133 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
134 {
135         MovePtr<TestTexture>    texture;
136         const VkImageType               imageType = getCompatibleImageType(viewType);
137
138         switch (imageType)
139         {
140                 case VK_IMAGE_TYPE_1D:
141                         if (layerCount == 1)
142                                 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
143                         else
144                                 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
145
146                         break;
147
148                 case VK_IMAGE_TYPE_2D:
149                         if (layerCount == 1)
150                         {
151                                 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
152                         }
153                         else
154                         {
155                                 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
156                                 {
157                                         if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
158                                         {
159                                                 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
160                                         }
161                                         else
162                                         {
163                                                 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
164
165                                                 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
166                                         }
167                                 }
168                                 else
169                                 {
170                                         texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
171                                 }
172                         }
173
174                         break;
175
176                 case VK_IMAGE_TYPE_3D:
177                         texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
178                         break;
179
180                 default:
181                         DE_ASSERT(false);
182         }
183
184         return texture;
185 }
186
187 } // anonymous
188
189 void checkSupportImageSamplingInstance (Context& context, ImageSamplingInstanceParams params)
190 {
191
192         if (de::abs(params.samplerParams.mipLodBias) > context.getDeviceProperties().limits.maxSamplerLodBias)
193                 TCU_THROW(NotSupportedError, "Unsupported sampler Lod bias value");
194
195         if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat))
196                 throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(params.imageFormat));
197
198         if ((deUint32)params.imageCount > context.getDeviceProperties().limits.maxColorAttachments)
199                 throw tcu::NotSupportedError(std::string("Unsupported render target count: ") + de::toString(params.imageCount));
200
201         if ((params.samplerParams.minFilter == VK_FILTER_LINEAR ||
202                  params.samplerParams.magFilter == VK_FILTER_LINEAR ||
203                  params.samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) &&
204                 !isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TILING_OPTIMAL))
205                 throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(params.imageFormat));
206
207         if (params.separateStencilUsage)
208         {
209                 context.requireDeviceFunctionality("VK_EXT_separate_stencil_usage");
210                 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
211
212                 const VkImageStencilUsageCreateInfo  stencilUsage       =
213                 {
214                         VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO,
215                         DE_NULL,
216                         VK_IMAGE_USAGE_TRANSFER_DST_BIT
217                 };
218
219                 const VkPhysicalDeviceImageFormatInfo2  formatInfo2             =
220                 {
221                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,          //      VkStructureType                 sType
222                         params.separateStencilUsage ? &stencilUsage
223                                                                                 : DE_NULL,                                              //      const void*                             pNext
224                         params.imageFormat,                                                                                     //      VkFormat                                format
225                         getCompatibleImageType(params.imageViewType),                           //      VkImageType                             type
226                         VK_IMAGE_TILING_OPTIMAL,                                                                        //      VkImageTiling                   tiling
227                         VK_IMAGE_USAGE_SAMPLED_BIT
228                         | VK_IMAGE_USAGE_TRANSFER_DST_BIT,                                                      //      VkImageUsageFlags               usage
229                         (VkImageCreateFlags)0u                                                                          //      VkImageCreateFlags              flags
230                 };
231
232                 VkImageFormatProperties2                                extProperties   =
233                 {
234                         VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
235                         DE_NULL,
236                         {
237                                 {
238                                         0,      // width
239                                         0,      // height
240                                         0,      // depth
241                                 },
242                                 0u,             // maxMipLevels
243                                 0u,             // maxArrayLayers
244                                 0,              // sampleCounts
245                                 0u,             // maxResourceSize
246                         },
247                 };
248
249                 if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &formatInfo2, &extProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
250                         || extProperties.imageFormatProperties.maxExtent.width < (deUint32)params.imageSize.x()
251                         || extProperties.imageFormatProperties.maxExtent.height < (deUint32)params.imageSize.y())
252                 {
253                         TCU_THROW(NotSupportedError, "Image format not supported");
254                 }
255         }
256
257         void const* pNext = params.samplerParams.pNext;
258         while (pNext != DE_NULL)
259         {
260                 const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext);
261                 switch (nextType)
262                 {
263                         case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
264                         {
265                                 context.requireDeviceFunctionality("VK_EXT_sampler_filter_minmax");
266
267                                 if (!isMinMaxFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TILING_OPTIMAL))
268                                         throw tcu::NotSupportedError(std::string("Unsupported format for min/max filtering: ") + getFormatName(params.imageFormat));
269
270                                 pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo*>(pNext)->pNext;
271                                 break;
272                         }
273                         case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
274                                 context.requireDeviceFunctionality("VK_KHR_sampler_ycbcr_conversion");
275
276                                 pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext;
277                                 break;
278                         case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT:
279                                 pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext)->pNext;
280
281                                 if (!context.getCustomBorderColorFeaturesEXT().customBorderColors)
282                                 {
283                                         throw tcu::NotSupportedError("customBorderColors feature is not supported");
284                                 }
285
286                                 break;
287                         default:
288                                 TCU_FAIL("Unrecognized sType in chained sampler create info");
289                 }
290         }
291
292         if (params.samplerParams.addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
293                 params.samplerParams.addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
294                 params.samplerParams.addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE)
295         {
296                 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
297         }
298
299         if ((isCompressedFormat(params.imageFormat) || isDepthStencilFormat(params.imageFormat)) && params.imageViewType == VK_IMAGE_VIEW_TYPE_3D)
300         {
301                 // \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED
302                 try
303                 {
304                         const VkImageFormatProperties   formatProperties        = getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(),
305                                                                                                                                                                                                                  context.getPhysicalDevice(),
306                                                                                                                                                                                                                  params.imageFormat,
307                                                                                                                                                                                                                  VK_IMAGE_TYPE_3D,
308                                                                                                                                                                                                                  VK_IMAGE_TILING_OPTIMAL,
309                                                                                                                                                                                                                  VK_IMAGE_USAGE_SAMPLED_BIT,
310                                                                                                                                                                                                                  (VkImageCreateFlags)0);
311
312                         if (formatProperties.maxExtent.width == 0 &&
313                                 formatProperties.maxExtent.height == 0 &&
314                                 formatProperties.maxExtent.depth == 0)
315                                 TCU_THROW(NotSupportedError, "3D compressed or depth format not supported");
316                 }
317                 catch (const Error&)
318                 {
319                         TCU_THROW(NotSupportedError, "3D compressed or depth format not supported");
320                 }
321         }
322
323         if (params.imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
324                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
325
326         if (params.allocationKind == ALLOCATION_KIND_DEDICATED)
327                 context.requireDeviceFunctionality("VK_KHR_dedicated_allocation");
328
329 #ifndef CTS_USES_VULKANSC
330         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset"))
331         {
332                 const auto portabilitySubsetFeatures    = context.getPortabilitySubsetFeatures();
333                 const auto componentMapping                             = params.componentMapping;
334                 if (!portabilitySubsetFeatures.imageViewFormatSwizzle &&
335                         ((componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY) ||
336                          (componentMapping.g != VK_COMPONENT_SWIZZLE_IDENTITY) ||
337                          (componentMapping.b != VK_COMPONENT_SWIZZLE_IDENTITY) ||
338                          (componentMapping.a != VK_COMPONENT_SWIZZLE_IDENTITY)))
339                 {
340                         TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support remapping format components");
341                 }
342         }
343
344         bool formatRgba10x6WithoutYCbCrSampler = context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler;
345 #else
346         bool formatRgba10x6WithoutYCbCrSampler = VK_FALSE;
347 #endif // CTS_USES_VULKANSC
348
349         if ((params.imageFormat == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16) && (params.subresourceRange.levelCount > 1) && (formatRgba10x6WithoutYCbCrSampler == VK_FALSE))
350         {
351                 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
352         }
353 }
354
355 ImageSamplingInstance::ImageSamplingInstance (Context&                                          context,
356                                                                                           ImageSamplingInstanceParams   params)
357         : vkt::TestInstance                             (context)
358         , m_allocationKind                              (params.allocationKind)
359         , m_samplingType                                (params.samplingType)
360         , m_imageViewType                               (params.imageViewType)
361         , m_imageFormat                                 (params.imageFormat)
362         , m_imageSize                                   (params.imageSize)
363         , m_layerCount                                  (params.layerCount)
364         , m_imageCount                                  (params.imageCount)
365         , m_componentMapping                    (params.componentMapping)
366         , m_componentMask                               (true)
367         , m_subresourceRange                    (params.subresourceRange)
368         , m_samplerParams                               (params.samplerParams)
369         , m_samplerLod                                  (params.samplerLod)
370         , m_renderSize                                  (params.renderSize)
371         , m_colorFormat                                 (VK_FORMAT_R8G8B8A8_UNORM)
372         , m_vertices                                    (params.vertices)
373         , m_graphicsPipeline                    (context.getDeviceInterface(), context.getDevice(), params.pipelineConstructionType, params.pipelineCreateFlags)
374         , m_pipelineConstructionType    (params.pipelineConstructionType)
375         , m_imageLayout                                 (params.imageLayout)
376 {
377 }
378
379 void ImageSamplingInstance::setup ()
380 {
381         const InstanceInterface&                                vki                                             = m_context.getInstanceInterface();
382         const DeviceInterface&                                  vk                                              = m_context.getDeviceInterface();
383         const VkPhysicalDevice                                  physDevice                              = m_context.getPhysicalDevice();
384         const VkDevice                                                  vkDevice                                = m_context.getDevice();
385         const VkQueue                                                   queue                                   = m_context.getUniversalQueue();
386         const deUint32                                                  queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
387         SimpleAllocator                                                 memAlloc                                (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
388         const VkComponentMapping                                componentMappingRGBA    = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
389
390         void const* pNext = m_samplerParams.pNext;
391         while (pNext != DE_NULL)
392         {
393                 const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext);
394                 switch (nextType)
395                 {
396                         case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
397                         {
398                                 VkPhysicalDeviceSamplerFilterMinmaxProperties   physicalDeviceSamplerMinMaxProperties =
399                                 {
400                                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES,
401                                         DE_NULL,
402                                         DE_FALSE,
403                                         DE_FALSE
404                                 };
405                                 VkPhysicalDeviceProperties2                                             physicalDeviceProperties;
406                                 physicalDeviceProperties.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
407                                 physicalDeviceProperties.pNext  = &physicalDeviceSamplerMinMaxProperties;
408
409                                 vki.getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties);
410
411                                 if (physicalDeviceSamplerMinMaxProperties.filterMinmaxImageComponentMapping != VK_TRUE)
412                                 {
413                                         // If filterMinmaxImageComponentMapping is VK_FALSE the component mapping of the image
414                                         // view used with min/max filtering must have been created with the r component set to
415                                         // VK_COMPONENT_SWIZZLE_IDENTITY. Only the r component of the sampled image value is
416                                         // defined and the other component values are undefined
417
418                                         m_componentMask = tcu::BVec4(true, false, false, false);
419
420                                         if (m_componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY && m_componentMapping.r != VK_COMPONENT_SWIZZLE_R)
421                                         {
422                                                 TCU_THROW(NotSupportedError, "filterMinmaxImageComponentMapping is not supported (R mapping is not IDENTITY)");
423                                         }
424                                 }
425                                 pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo*>(pNext)->pNext;
426                         }
427                         break;
428                         case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
429                                 pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext;
430                                 break;
431                         case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT:
432                         {
433                                 const VkSamplerCustomBorderColorCreateInfoEXT customBorderColorCreateInfo = *reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext);
434
435                                 VkPhysicalDeviceCustomBorderColorFeaturesEXT    physicalDeviceCustomBorderColorFeatures =
436                                 {
437                                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT,
438                                         DE_NULL,
439                                         DE_FALSE,
440                                         DE_FALSE
441                                 };
442                                 VkPhysicalDeviceFeatures2                                               physicalDeviceFeatures;
443                                 physicalDeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
444                                 physicalDeviceFeatures.pNext = &physicalDeviceCustomBorderColorFeatures;
445
446                                 vki.getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &physicalDeviceFeatures);
447
448                                 if (physicalDeviceCustomBorderColorFeatures.customBorderColors != VK_TRUE)
449                                 {
450                                         TCU_THROW(NotSupportedError, "customBorderColors are not supported");
451                                 }
452
453                                 if (physicalDeviceCustomBorderColorFeatures.customBorderColorWithoutFormat != VK_TRUE &&
454                                         customBorderColorCreateInfo.format == VK_FORMAT_UNDEFINED)
455                                 {
456                                         TCU_THROW(NotSupportedError, "customBorderColorWithoutFormat is not supported");
457                                 }
458
459                                 pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext)->pNext;
460                         }
461                         break;
462                         default:
463                                 TCU_FAIL("Unrecognized sType in chained sampler create info");
464                 }
465         }
466
467         // Create texture images, views and samplers
468         {
469                 VkImageCreateFlags                      imageFlags                      = 0u;
470
471                 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
472                         imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
473
474                 // Initialize texture data
475                 if (isCompressedFormat(m_imageFormat))
476                         m_texture = createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
477                 else
478                         m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
479
480                 const VkImageCreateInfo imageParams =
481                 {
482                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                    // VkStructureType                      sType;
483                         DE_NULL,                                                                                                                // const void*                          pNext;
484                         imageFlags,                                                                                                             // VkImageCreateFlags           flags;
485                         getCompatibleImageType(m_imageViewType),                                                // VkImageType                          imageType;
486                         m_imageFormat,                                                                                                  // VkFormat                                     format;
487                         {                                                                                                                               // VkExtent3D                           extent;
488                                 (deUint32)m_imageSize.x(),
489                                 (deUint32)m_imageSize.y(),
490                                 (deUint32)m_imageSize.z()
491                         },
492                         (deUint32)m_texture->getNumLevels(),                                                    // deUint32                                     mipLevels;
493                         (deUint32)m_layerCount,                                                                                 // deUint32                                     arrayLayers;
494                         VK_SAMPLE_COUNT_1_BIT,                                                                                  // VkSampleCountFlagBits        samples;
495                         VK_IMAGE_TILING_OPTIMAL,                                                                                // VkImageTiling                        tiling;
496                         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,   // VkImageUsageFlags            usage;
497                         VK_SHARING_MODE_EXCLUSIVE,                                                                              // VkSharingMode                        sharingMode;
498                         1u,                                                                                                                             // deUint32                                     queueFamilyIndexCount;
499                         &queueFamilyIndex,                                                                                              // const deUint32*                      pQueueFamilyIndices;
500                         VK_IMAGE_LAYOUT_UNDEFINED                                                                               // VkImageLayout                        initialLayout;
501                 };
502
503                 m_images.resize(m_imageCount);
504                 m_imageAllocs.resize(m_imageCount);
505                 m_imageViews.resize(m_imageCount);
506
507                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
508                 {
509                         m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
510                         m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
511                         VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset()));
512
513                         // Upload texture data
514                         uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx]);
515
516                         // Create image view and sampler
517                         const VkImageViewCreateInfo imageViewParams =
518                         {
519                                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                      sType;
520                                 DE_NULL,                                                                        // const void*                          pNext;
521                                 0u,                                                                                     // VkImageViewCreateFlags       flags;
522                                 **m_images[imgNdx],                                                     // VkImage                                      image;
523                                 m_imageViewType,                                                        // VkImageViewType                      viewType;
524                                 m_imageFormat,                                                          // VkFormat                                     format;
525                                 m_componentMapping,                                                     // VkComponentMapping           components;
526                                 m_subresourceRange,                                                     // VkImageSubresourceRange      subresourceRange;
527                         };
528
529                         m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
530                 }
531
532                 m_sampler       = createSampler(vk, vkDevice, &m_samplerParams);
533         }
534
535         // Create descriptor set for image and sampler
536         {
537                 DescriptorPoolBuilder descriptorPoolBuilder;
538                 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
539                         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
540                 descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
541                 m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
542                         m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
543
544                 DescriptorSetLayoutBuilder setLayoutBuilder;
545                 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
546                         setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
547                 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
548                 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
549
550                 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
551                 {
552                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
553                         DE_NULL,                                                                                        // const void*                                  pNext;
554                         *m_descriptorPool,                                                                      // VkDescriptorPool                             descriptorPool;
555                         1u,                                                                                                     // deUint32                                             setLayoutCount;
556                         &m_descriptorSetLayout.get()                                            // const VkDescriptorSetLayout* pSetLayouts;
557                 };
558
559                 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
560
561                 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
562                 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
563                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
564                 {
565                         descriptorImageInfo[imgNdx].sampler             = sampler;                                                                      // VkSampler            sampler;
566                         descriptorImageInfo[imgNdx].imageView   = **m_imageViews[imgNdx];                                       // VkImageView          imageView;
567                         descriptorImageInfo[imgNdx].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;     // VkImageLayout        imageLayout;
568                 }
569
570                 DescriptorSetUpdateBuilder setUpdateBuilder;
571                 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
572                 {
573                         const VkDescriptorImageInfo descriptorSamplerInfo =
574                         {
575                                 *m_sampler,                                                                     // VkSampler            sampler;
576                                 DE_NULL,                                                                        // VkImageView          imageView;
577                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL        // VkImageLayout        imageLayout;
578                         };
579                         setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
580                 }
581
582                 const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
583                 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data());
584                 setUpdateBuilder.update(vk, vkDevice);
585         }
586
587         // Create color images and views
588         {
589                 const VkImageCreateInfo colorImageParams =
590                 {
591                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
592                         DE_NULL,                                                                                                                                        // const void*                          pNext;
593                         0u,                                                                                                                                                     // VkImageCreateFlags           flags;
594                         VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
595                         m_colorFormat,                                                                                                                          // VkFormat                                     format;
596                         { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },                         // VkExtent3D                           extent;
597                         1u,                                                                                                                                                     // deUint32                                     mipLevels;
598                         1u,                                                                                                                                                     // deUint32                                     arrayLayers;
599                         VK_SAMPLE_COUNT_1_BIT,                                                                                                          // VkSampleCountFlagBits        samples;
600                         VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                        tiling;
601                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,          // VkImageUsageFlags            usage;
602                         VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                        sharingMode;
603                         1u,                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
604                         &queueFamilyIndex,                                                                                                                      // const deUint32*                      pQueueFamilyIndices;
605                         VK_IMAGE_LAYOUT_UNDEFINED                                                                                                       // VkImageLayout                        initialLayout;
606                 };
607
608                 m_colorImages.resize(m_imageCount);
609                 m_colorImageAllocs.resize(m_imageCount);
610                 m_colorAttachmentViews.resize(m_imageCount);
611
612                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
613                 {
614                         m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
615                         m_colorImageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
616                         VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(), (*m_colorImageAllocs[imgNdx])->getOffset()));
617
618                         const VkImageViewCreateInfo colorAttachmentViewParams =
619                         {
620                                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       // VkStructureType                      sType;
621                                 DE_NULL,                                                                                        // const void*                          pNext;
622                                 0u,                                                                                                     // VkImageViewCreateFlags       flags;
623                                 **m_colorImages[imgNdx],                                                        // VkImage                                      image;
624                                 VK_IMAGE_VIEW_TYPE_2D,                                                          // VkImageViewType                      viewType;
625                                 m_colorFormat,                                                                          // VkFormat                                     format;
626                                 componentMappingRGBA,                                                           // VkComponentMapping           components;
627                                 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }           // VkImageSubresourceRange      subresourceRange;
628                         };
629
630                         m_colorAttachmentViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
631                 }
632         }
633
634         // Create render pass
635         {
636                 std::vector<VkAttachmentDescription>    colorAttachmentDescriptions(m_imageCount);
637                 std::vector<VkAttachmentReference>              colorAttachmentReferences(m_imageCount);
638
639                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
640                 {
641                         colorAttachmentDescriptions[imgNdx].flags                       = 0u;                                                                           // VkAttachmentDescriptionFlags         flags;
642                         colorAttachmentDescriptions[imgNdx].format                      = m_colorFormat;                                                        // VkFormat                                                     format;
643                         colorAttachmentDescriptions[imgNdx].samples                     = VK_SAMPLE_COUNT_1_BIT;                                        // VkSampleCountFlagBits                        samples;
644                         colorAttachmentDescriptions[imgNdx].loadOp                      = VK_ATTACHMENT_LOAD_OP_CLEAR;                          // VkAttachmentLoadOp                           loadOp;
645                         colorAttachmentDescriptions[imgNdx].storeOp                     = VK_ATTACHMENT_STORE_OP_STORE;                         // VkAttachmentStoreOp                          storeOp;
646                         colorAttachmentDescriptions[imgNdx].stencilLoadOp       = VK_ATTACHMENT_LOAD_OP_DONT_CARE;                      // VkAttachmentLoadOp                           stencilLoadOp;
647                         colorAttachmentDescriptions[imgNdx].stencilStoreOp      = VK_ATTACHMENT_STORE_OP_DONT_CARE;                     // VkAttachmentStoreOp                          stencilStoreOp;
648                         colorAttachmentDescriptions[imgNdx].initialLayout       = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;     // VkImageLayout                                        initialLayout;
649                         colorAttachmentDescriptions[imgNdx].finalLayout         = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;     // VkImageLayout                                        finalLayout;
650
651                         colorAttachmentReferences[imgNdx].attachment            = (deUint32)imgNdx;                                                     // deUint32                                                     attachment;
652                         colorAttachmentReferences[imgNdx].layout                        = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;     // VkImageLayout                                        layout;
653                 }
654
655                 const VkSubpassDescription subpassDescription =
656                 {
657                         0u,                                                                                                     // VkSubpassDescriptionFlags    flags;
658                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                  pipelineBindPoint;
659                         0u,                                                                                                     // deUint32                                             inputAttachmentCount;
660                         DE_NULL,                                                                                        // const VkAttachmentReference* pInputAttachments;
661                         (deUint32)m_imageCount,                                                         // deUint32                                             colorAttachmentCount;
662                         &colorAttachmentReferences[0],                                          // const VkAttachmentReference* pColorAttachments;
663                         DE_NULL,                                                                                        // const VkAttachmentReference* pResolveAttachments;
664                         DE_NULL,                                                                                        // const VkAttachmentReference* pDepthStencilAttachment;
665                         0u,                                                                                                     // deUint32                                             preserveAttachmentCount;
666                         DE_NULL                                                                                         // const VkAttachmentReference* pPreserveAttachments;
667                 };
668
669                 const VkRenderPassCreateInfo renderPassParams =
670                 {
671                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
672                         DE_NULL,                                                                                        // const void*                                          pNext;
673                         0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
674                         (deUint32)m_imageCount,                                                         // deUint32                                                     attachmentCount;
675                         &colorAttachmentDescriptions[0],                                        // const VkAttachmentDescription*       pAttachments;
676                         1u,                                                                                                     // deUint32                                                     subpassCount;
677                         &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
678                         0u,                                                                                                     // deUint32                                                     dependencyCount;
679                         DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
680                 };
681
682                 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
683         }
684
685         // Create framebuffer
686         {
687                 std::vector<VkImageView> pAttachments(m_imageCount);
688                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
689                         pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
690
691                 const VkFramebufferCreateInfo framebufferParams =
692                 {
693                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                      sType;
694                         DE_NULL,                                                                                        // const void*                          pNext;
695                         0u,                                                                                                     // VkFramebufferCreateFlags     flags;
696                         *m_renderPass,                                                                          // VkRenderPass                         renderPass;
697                         (deUint32)m_imageCount,                                                         // deUint32                                     attachmentCount;
698                         &pAttachments[0],                                                                       // const VkImageView*           pAttachments;
699                         (deUint32)m_renderSize.x(),                                                     // deUint32                                     width;
700                         (deUint32)m_renderSize.y(),                                                     // deUint32                                     height;
701                         1u                                                                                                      // deUint32                                     layers;
702                 };
703
704                 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
705         }
706
707         // Create pipeline layout
708         {
709 #ifndef CTS_USES_VULKANSC
710                 VkPipelineLayoutCreateFlags pipelineLayoutFlags = (m_pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
711 #else
712                 VkPipelineLayoutCreateFlags pipelineLayoutFlags = 0u;
713 #endif // CTS_USES_VULKANSC
714                 VkPipelineLayoutCreateInfo      pipelineLayoutParams
715                 {
716                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
717                         DE_NULL,                                                                                        // const void*                                  pNext;
718                         pipelineLayoutFlags,                                                            // VkPipelineLayoutCreateFlags  flags;
719                         0u,                                                                                                     // deUint32                                             setLayoutCount;
720                         DE_NULL,                                                                                        // const VkDescriptorSetLayout* pSetLayouts;
721                         0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
722                         DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
723                 };
724
725                 m_preRasterizationStatePipelineLayout   = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
726                 pipelineLayoutParams.setLayoutCount             = 1u;
727                 pipelineLayoutParams.pSetLayouts                = &m_descriptorSetLayout.get();
728                 m_fragmentStatePipelineLayout                   = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
729         }
730
731         m_vertexShaderModule    = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
732         m_fragmentShaderModule  = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
733
734         // Create pipeline
735         {
736                 const VkVertexInputBindingDescription vertexInputBindingDescription =
737                 {
738                         0u,                                                                     // deUint32                                     binding;
739                         sizeof(Vertex4Tex4),                            // deUint32                                     strideInBytes;
740                         VK_VERTEX_INPUT_RATE_VERTEX                     // VkVertexInputStepRate        inputRate;
741                 };
742
743                 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
744                 {
745                         {
746                                 0u,                                                                             // deUint32     location;
747                                 0u,                                                                             // deUint32     binding;
748                                 VK_FORMAT_R32G32B32A32_SFLOAT,                  // VkFormat     format;
749                                 0u                                                                              // deUint32     offset;
750                         },
751                         {
752                                 1u,                                                                             // deUint32     location;
753                                 0u,                                                                             // deUint32     binding;
754                                 VK_FORMAT_R32G32B32A32_SFLOAT,                  // VkFormat     format;
755                                 DE_OFFSET_OF(Vertex4Tex4, texCoord),    // deUint32     offset;
756                         }
757                 };
758
759                 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
760                 {
761                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
762                         DE_NULL,                                                                                                                // const void*                                                          pNext;
763                         0u,                                                                                                                             // VkPipelineVertexInputStateCreateFlags        flags;
764                         1u,                                                                                                                             // deUint32                                                                     vertexBindingDescriptionCount;
765                         &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
766                         2u,                                                                                                                             // deUint32                                                                     vertexAttributeDescriptionCount;
767                         vertexInputAttributeDescriptions                                                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
768                 };
769
770                 const std::vector<VkViewport>   viewports       { makeViewport(m_renderSize) };
771                 const std::vector<VkRect2D>             scissors        { makeRect2D(m_renderSize) };
772
773                 std::vector<VkPipelineColorBlendAttachmentState>        colorBlendAttachmentStates(m_imageCount);
774
775                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
776                 {
777                         colorBlendAttachmentStates[imgNdx].blendEnable                  = false;                                                                                                // VkBool32                                     blendEnable;
778                         colorBlendAttachmentStates[imgNdx].srcColorBlendFactor  = VK_BLEND_FACTOR_ONE;                                                                  // VkBlendFactor                        srcColorBlendFactor;
779                         colorBlendAttachmentStates[imgNdx].dstColorBlendFactor  = VK_BLEND_FACTOR_ZERO;                                                                 // VkBlendFactor                        dstColorBlendFactor;
780                         colorBlendAttachmentStates[imgNdx].colorBlendOp                 = VK_BLEND_OP_ADD;                                                                              // VkBlendOp                            colorBlendOp;
781                         colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor  = VK_BLEND_FACTOR_ONE;                                                                  // VkBlendFactor                        srcAlphaBlendFactor;
782                         colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor  = VK_BLEND_FACTOR_ZERO;                                                                 // VkBlendFactor                        dstAlphaBlendFactor;
783                         colorBlendAttachmentStates[imgNdx].alphaBlendOp                 = VK_BLEND_OP_ADD;                                                                              // VkBlendOp                            alphaBlendOp;
784                         colorBlendAttachmentStates[imgNdx].colorWriteMask               = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags        colorWriteMask;
785                                                                                                                                                 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
786                 }
787
788                 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
789                 {
790                         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
791                         DE_NULL,                                                                                                        // const void*                                                                  pNext;
792                         0u,                                                                                                                     // VkPipelineColorBlendStateCreateFlags                 flags;
793                         false,                                                                                                          // VkBool32                                                                             logicOpEnable;
794                         VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
795                         (deUint32)m_imageCount,                                                                         // deUint32                                                                             attachmentCount;
796                         &colorBlendAttachmentStates[0],                                                         // const VkPipelineColorBlendAttachmentState*   pAttachments;
797                         { 0.0f, 0.0f, 0.0f, 0.0f }                                                                      // float                                                                                blendConstants[4];
798                 };
799
800                 m_graphicsPipeline.setMonolithicPipelineLayout(*m_fragmentStatePipelineLayout)
801                                                   .setDefaultDepthStencilState()
802                                                   .setDefaultRasterizationState()
803                                                   .setDefaultMultisampleState()
804                                                   .setupVertexInputState(&vertexInputStateParams)
805                                                   .setupPreRasterizationShaderState(viewports,
806                                                                                                                 scissors,
807                                                                                                                 *m_preRasterizationStatePipelineLayout,
808                                                                                                                 *m_renderPass,
809                                                                                                                 0u,
810                                                                                                                 *m_vertexShaderModule)
811                                                   .setupFragmentShaderState(*m_fragmentStatePipelineLayout, *m_renderPass, 0u, *m_fragmentShaderModule)
812                                                   .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
813                                                   .buildPipeline();
814         }
815
816         // Create vertex buffer
817         {
818                 const VkDeviceSize                      vertexBufferSize        = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
819                 const VkBufferCreateInfo        vertexBufferParams      =
820                 {
821                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
822                         DE_NULL,                                                                        // const void*                  pNext;
823                         0u,                                                                                     // VkBufferCreateFlags  flags;
824                         vertexBufferSize,                                                       // VkDeviceSize                 size;
825                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
826                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
827                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
828                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
829                 };
830
831                 DE_ASSERT(vertexBufferSize > 0);
832
833                 m_vertexBuffer          = createBuffer(vk, vkDevice, &vertexBufferParams);
834                 m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
835                 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
836
837                 // Load vertices into vertex buffer
838                 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
839                 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
840         }
841
842         // Create command pool
843         m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
844
845         // Create command buffer
846         {
847                 const std::vector<VkClearValue> attachmentClearValues (m_imageCount, defaultClearValue(m_colorFormat));
848
849                 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
850
851                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
852                 {
853                         preAttachmentBarriers[imgNdx].sType                                                             = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;       // VkStructureType                      sType;
854                         preAttachmentBarriers[imgNdx].pNext                                                             = DE_NULL;                                                                      // const void*                          pNext;
855                         preAttachmentBarriers[imgNdx].srcAccessMask                                             = 0u;                                                                           // VkAccessFlags                        srcAccessMask;
856                         preAttachmentBarriers[imgNdx].dstAccessMask                                             = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;         // VkAccessFlags                        dstAccessMask;
857                         preAttachmentBarriers[imgNdx].oldLayout                                                 = VK_IMAGE_LAYOUT_UNDEFINED;                            // VkImageLayout                        oldLayout;
858                         preAttachmentBarriers[imgNdx].newLayout                                                 = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;     // VkImageLayout                        newLayout;
859                         preAttachmentBarriers[imgNdx].srcQueueFamilyIndex                               = VK_QUEUE_FAMILY_IGNORED;                                      // deUint32                                     srcQueueFamilyIndex;
860                         preAttachmentBarriers[imgNdx].dstQueueFamilyIndex                               = VK_QUEUE_FAMILY_IGNORED;                                      // deUint32                                     dstQueueFamilyIndex;
861                         preAttachmentBarriers[imgNdx].image                                                             = **m_colorImages[imgNdx];                                      // VkImage                                      image;
862                         preAttachmentBarriers[imgNdx].subresourceRange.aspectMask               = VK_IMAGE_ASPECT_COLOR_BIT;                            // VkImageSubresourceRange      subresourceRange;
863                         preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel             = 0u;
864                         preAttachmentBarriers[imgNdx].subresourceRange.levelCount               = 1u;
865                         preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer   = 0u;
866                         preAttachmentBarriers[imgNdx].subresourceRange.layerCount               = 1u;
867                 }
868
869                 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
870
871                 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
872
873                 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
874                         0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
875
876                 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), &attachmentClearValues[0]);
877
878                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline.getPipeline());
879
880                 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
881
882                 const VkDeviceSize vertexBufferOffset = 0;
883                 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
884                 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
885
886                 endRenderPass(vk, *m_cmdBuffer);
887                 endCommandBuffer(vk, *m_cmdBuffer);
888         }
889 }
890
891 ImageSamplingInstance::~ImageSamplingInstance (void)
892 {
893 }
894
895 tcu::TestStatus ImageSamplingInstance::iterate (void)
896 {
897         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
898         const VkDevice                          vkDevice        = m_context.getDevice();
899         const VkQueue                           queue           = m_context.getUniversalQueue();
900
901         setup();
902
903         submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
904
905         return verifyImage();
906 }
907
908 namespace
909 {
910
911 bool isLookupResultValid (const tcu::Texture1DView&             texture,
912                                                   const tcu::Sampler&                   sampler,
913                                                   const tcu::LookupPrecision&   precision,
914                                                   const tcu::Vec4&                              coords,
915                                                   const tcu::Vec2&                              lodBounds,
916                                                   const tcu::Vec4&                              result)
917 {
918         return tcu::isLookupResultValid(texture, sampler, precision, coords.x(), lodBounds, result);
919 }
920
921 bool isLookupResultValid (const tcu::Texture1DArrayView&        texture,
922                                                   const tcu::Sampler&                           sampler,
923                                                   const tcu::LookupPrecision&           precision,
924                                                   const tcu::Vec4&                                      coords,
925                                                   const tcu::Vec2&                                      lodBounds,
926                                                   const tcu::Vec4&                                      result)
927 {
928         return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
929 }
930
931 bool isLookupResultValid (const tcu::Texture2DView&             texture,
932                                                   const tcu::Sampler&                   sampler,
933                                                   const tcu::LookupPrecision&   precision,
934                                                   const tcu::Vec4&                              coords,
935                                                   const tcu::Vec2&                              lodBounds,
936                                                   const tcu::Vec4&                              result)
937 {
938         return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
939 }
940
941 bool isLookupResultValid (const tcu::Texture2DArrayView&        texture,
942                                                   const tcu::Sampler&                           sampler,
943                                                   const tcu::LookupPrecision&           precision,
944                                                   const tcu::Vec4&                                      coords,
945                                                   const tcu::Vec2&                                      lodBounds,
946                                                   const tcu::Vec4&                                      result)
947 {
948         return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
949 }
950
951 bool isLookupResultValid (const tcu::TextureCubeView&   texture,
952                                                   const tcu::Sampler&                   sampler,
953                                                   const tcu::LookupPrecision&   precision,
954                                                   const tcu::Vec4&                              coords,
955                                                   const tcu::Vec2&                              lodBounds,
956                                                   const tcu::Vec4&                              result)
957 {
958         return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
959 }
960
961 bool isLookupResultValid (const tcu::TextureCubeArrayView&      texture,
962                                                   const tcu::Sampler&                           sampler,
963                                                   const tcu::LookupPrecision&           precision,
964                                                   const tcu::Vec4&                                      coords,
965                                                   const tcu::Vec2&                                      lodBounds,
966                                                   const tcu::Vec4&                                      result)
967 {
968         return tcu::isLookupResultValid(texture, sampler, precision, tcu::IVec4(precision.coordBits.x()), coords, lodBounds, result);
969 }
970
971 bool isLookupResultValid(const tcu::Texture3DView&              texture,
972                                                  const tcu::Sampler&                    sampler,
973                                                  const tcu::LookupPrecision&    precision,
974                                                  const tcu::Vec4&                               coords,
975                                                  const tcu::Vec2&                               lodBounds,
976                                                  const tcu::Vec4&                               result)
977 {
978         return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
979 }
980
981 template<typename TextureViewType>
982 bool validateResultImage (const TextureViewType&                                texture,
983                                                   const tcu::Sampler&                                   sampler,
984                                                   const tcu::ConstPixelBufferAccess&    texCoords,
985                                                   const tcu::Vec2&                                              lodBounds,
986                                                   const tcu::LookupPrecision&                   lookupPrecision,
987                                                   const tcu::Vec4&                                              lookupScale,
988                                                   const tcu::Vec4&                                              lookupBias,
989                                                   const tcu::ConstPixelBufferAccess&    result,
990                                                   const tcu::PixelBufferAccess&                 errorMask)
991 {
992         const int       w               = result.getWidth();
993         const int       h               = result.getHeight();
994         bool            allOk   = true;
995
996         for (int y = 0; y < h; ++y)
997         {
998                 for (int x = 0; x < w; ++x)
999                 {
1000                         const tcu::Vec4         resultPixel     = result.getPixel(x, y);
1001                         const tcu::Vec4         resultColor     = (resultPixel - lookupBias) / lookupScale;
1002                         const tcu::Vec4         texCoord        = texCoords.getPixel(x, y);
1003                         const bool                      pixelOk         = isLookupResultValid(texture, sampler, lookupPrecision, texCoord, lodBounds, resultColor);
1004
1005                         errorMask.setPixel(tcu::Vec4(pixelOk?0.0f:1.0f, pixelOk?1.0f:0.0f, 0.0f, 1.0f), x, y);
1006
1007                         if (!pixelOk)
1008                                 allOk = false;
1009                 }
1010         }
1011
1012         return allOk;
1013 }
1014
1015 template<typename ScalarType>
1016 ScalarType getSwizzledComp (const tcu::Vector<ScalarType, 4>& vec, vk::VkComponentSwizzle comp, int identityNdx)
1017 {
1018         if (comp == vk::VK_COMPONENT_SWIZZLE_IDENTITY)
1019                 return vec[identityNdx];
1020         else if (comp == vk::VK_COMPONENT_SWIZZLE_ZERO)
1021                 return ScalarType(0);
1022         else if (comp == vk::VK_COMPONENT_SWIZZLE_ONE)
1023                 return ScalarType(1);
1024         else
1025                 return vec[comp - vk::VK_COMPONENT_SWIZZLE_R];
1026 }
1027
1028 template<typename ScalarType>
1029 tcu::Vector<ScalarType, 4> swizzle (const tcu::Vector<ScalarType, 4>& vec, const vk::VkComponentMapping& swz)
1030 {
1031         return tcu::Vector<ScalarType, 4>(getSwizzledComp(vec, swz.r, 0),
1032                                                                           getSwizzledComp(vec, swz.g, 1),
1033                                                                           getSwizzledComp(vec, swz.b, 2),
1034                                                                           getSwizzledComp(vec, swz.a, 3));
1035 }
1036
1037 /*--------------------------------------------------------------------*//*!
1038 * \brief Swizzle scale or bias vector by given mapping
1039 *
1040 * \param vec scale or bias vector
1041 * \param swz swizzle component mapping, may include ZERO, ONE, or IDENTITY
1042 * \param zeroOrOneValue vector value for component swizzled as ZERO or ONE
1043 * \return swizzled vector
1044 *//*--------------------------------------------------------------------*/
1045 tcu::Vec4 swizzleScaleBias (const tcu::Vec4& vec, const vk::VkComponentMapping& swz, float zeroOrOneValue)
1046 {
1047
1048         // Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
1049         const vk::VkComponentMapping nonIdentitySwz =
1050         {
1051                 swz.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : swz.r,
1052                 swz.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : swz.g,
1053                 swz.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : swz.b,
1054                 swz.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : swz.a
1055         };
1056
1057         const float channelValues[] =
1058         {
1059                 -1.0f,                          // impossible
1060                 zeroOrOneValue,         // SWIZZLE_ZERO
1061                 zeroOrOneValue,         // SWIZZLE_ONE
1062                 vec.x(),
1063                 vec.y(),
1064                 vec.z(),
1065                 vec.w(),
1066         };
1067
1068         return tcu::Vec4(channelValues[nonIdentitySwz.r], channelValues[nonIdentitySwz.g], channelValues[nonIdentitySwz.b], channelValues[nonIdentitySwz.a]);
1069 }
1070
1071 template<typename ScalarType>
1072 void swizzleT (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1073 {
1074         for (int z = 0; z < dst.getDepth(); ++z)
1075         for (int y = 0; y < dst.getHeight(); ++y)
1076         for (int x = 0; x < dst.getWidth(); ++x)
1077                 dst.setPixel(swizzle(src.getPixelT<ScalarType>(x, y, z), swz), x, y, z);
1078 }
1079
1080 void swizzleFromSRGB (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1081 {
1082         for (int z = 0; z < dst.getDepth(); ++z)
1083         for (int y = 0; y < dst.getHeight(); ++y)
1084         for (int x = 0; x < dst.getWidth(); ++x)
1085                 dst.setPixel(swizzle(tcu::sRGBToLinear(src.getPixelT<float>(x, y, z)), swz), x, y, z);
1086 }
1087
1088 void swizzle (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1089 {
1090         const tcu::TextureChannelClass  chnClass        = tcu::getTextureChannelClass(dst.getFormat().type);
1091
1092         DE_ASSERT(src.getWidth() == dst.getWidth() &&
1093                           src.getHeight() == dst.getHeight() &&
1094                           src.getDepth() == dst.getDepth());
1095
1096         if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1097                 swizzleT<deInt32>(src, dst, swz);
1098         else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1099                 swizzleT<deUint32>(src, dst, swz);
1100         else if (tcu::isSRGB(src.getFormat()) && !tcu::isSRGB(dst.getFormat()))
1101                 swizzleFromSRGB(src, dst, swz);
1102         else
1103                 swizzleT<float>(src, dst, swz);
1104 }
1105
1106 bool isIdentitySwizzle (const vk::VkComponentMapping& swz)
1107 {
1108         return (swz.r == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.r == vk::VK_COMPONENT_SWIZZLE_R) &&
1109                    (swz.g == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.g == vk::VK_COMPONENT_SWIZZLE_G) &&
1110                    (swz.b == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.b == vk::VK_COMPONENT_SWIZZLE_B) &&
1111                    (swz.a == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.a == vk::VK_COMPONENT_SWIZZLE_A);
1112 }
1113
1114 template<typename TextureViewType> struct TexViewTraits;
1115
1116 template<> struct TexViewTraits<tcu::Texture1DView>                     { typedef tcu::Texture1D                TextureType; };
1117 template<> struct TexViewTraits<tcu::Texture1DArrayView>        { typedef tcu::Texture1DArray   TextureType; };
1118 template<> struct TexViewTraits<tcu::Texture2DView>                     { typedef tcu::Texture2D                TextureType; };
1119 template<> struct TexViewTraits<tcu::Texture2DArrayView>        { typedef tcu::Texture2DArray   TextureType; };
1120 template<> struct TexViewTraits<tcu::TextureCubeView>           { typedef tcu::TextureCube              TextureType; };
1121 template<> struct TexViewTraits<tcu::TextureCubeArrayView>      { typedef tcu::TextureCubeArray TextureType; };
1122 template<> struct TexViewTraits<tcu::Texture3DView>                     { typedef tcu::Texture3D                TextureType; };
1123
1124 template<typename TextureViewType>
1125 typename TexViewTraits<TextureViewType>::TextureType* createSkeletonClone (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0);
1126
1127 tcu::TextureFormat getSwizzleTargetFormat (tcu::TextureFormat format)
1128 {
1129         // Swizzled texture needs to hold all four channels
1130         // \todo [2016-09-21 pyry] We could save some memory by using smaller formats
1131         //                                                 when possible (for example U8).
1132
1133         const tcu::TextureChannelClass  chnClass        = tcu::getTextureChannelClass(format.type);
1134
1135         if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1136                 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1137         else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1138                 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1139         else
1140                 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1141 }
1142
1143 template<>
1144 tcu::Texture1D* createSkeletonClone<tcu::Texture1DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1145 {
1146         return new tcu::Texture1D(format, level0.getWidth());
1147 }
1148
1149 template<>
1150 tcu::Texture1DArray* createSkeletonClone<tcu::Texture1DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1151 {
1152         return new tcu::Texture1DArray(format, level0.getWidth(), level0.getHeight());
1153 }
1154
1155 template<>
1156 tcu::Texture2D* createSkeletonClone<tcu::Texture2DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1157 {
1158         return new tcu::Texture2D(format, level0.getWidth(), level0.getHeight());
1159 }
1160
1161 template<>
1162 tcu::Texture2DArray* createSkeletonClone<tcu::Texture2DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1163 {
1164         return new tcu::Texture2DArray(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1165 }
1166
1167 template<>
1168 tcu::Texture3D* createSkeletonClone<tcu::Texture3DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1169 {
1170         return new tcu::Texture3D(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1171 }
1172
1173 template<>
1174 tcu::TextureCubeArray* createSkeletonClone<tcu::TextureCubeArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1175 {
1176         return new tcu::TextureCubeArray(format, level0.getWidth(), level0.getDepth());
1177 }
1178
1179 template<typename TextureViewType>
1180 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> createSwizzledCopy (const TextureViewType& texture, const vk::VkComponentMapping& swz)
1181 {
1182         MovePtr<typename TexViewTraits<TextureViewType>::TextureType>   copy    (createSkeletonClone<TextureViewType>(getSwizzleTargetFormat(texture.getLevel(0).getFormat()), texture.getLevel(0)));
1183
1184         for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1185         {
1186                 copy->allocLevel(levelNdx);
1187                 swizzle(texture.getLevel(levelNdx), copy->getLevel(levelNdx), swz);
1188         }
1189
1190         return copy;
1191 }
1192
1193 template<>
1194 MovePtr<tcu::TextureCube> createSwizzledCopy (const tcu::TextureCubeView& texture, const vk::VkComponentMapping& swz)
1195 {
1196         MovePtr<tcu::TextureCube>       copy    (new tcu::TextureCube(getSwizzleTargetFormat(texture.getLevelFace(0, tcu::CUBEFACE_NEGATIVE_X).getFormat()), texture.getSize()));
1197
1198         for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1199         {
1200                 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1201                 {
1202                         copy->allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1203                         swizzle(texture.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), copy->getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), swz);
1204                 }
1205         }
1206
1207         return copy;
1208 }
1209
1210 template<typename TextureViewType>
1211 bool validateResultImage (const TextureViewType&                                texture,
1212                                                   const tcu::Sampler&                                   sampler,
1213                                                   const vk::VkComponentMapping&                 swz,
1214                                                   const tcu::ConstPixelBufferAccess&    texCoords,
1215                                                   const tcu::Vec2&                                              lodBounds,
1216                                                   const tcu::LookupPrecision&                   lookupPrecision,
1217                                                   const tcu::Vec4&                                              lookupScale,
1218                                                   const tcu::Vec4&                                              lookupBias,
1219                                                   const tcu::ConstPixelBufferAccess&    result,
1220                                                   const tcu::PixelBufferAccess&                 errorMask)
1221 {
1222         if (isIdentitySwizzle(swz))
1223                 return validateResultImage(texture, sampler, texCoords, lodBounds, lookupPrecision, lookupScale, lookupBias, result, errorMask);
1224         else
1225         {
1226                 // There is (currently) no way to handle swizzling inside validation loop
1227                 // and thus we need to pre-swizzle the texture.
1228                 UniquePtr<typename TexViewTraits<TextureViewType>::TextureType> swizzledTex     (createSwizzledCopy(texture, swz));
1229
1230                 return validateResultImage(*swizzledTex, sampler, texCoords, lodBounds, lookupPrecision, swizzleScaleBias(lookupScale, swz, 1.0f), swizzleScaleBias(lookupBias, swz, 0.0f), result, errorMask);
1231         }
1232 }
1233
1234 vk::VkImageSubresourceRange resolveSubresourceRange (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource)
1235 {
1236         vk::VkImageSubresourceRange     resolved                                        = subresource;
1237
1238         if (subresource.levelCount == VK_REMAINING_MIP_LEVELS)
1239                 resolved.levelCount = testTexture.getNumLevels()-subresource.baseMipLevel;
1240
1241         if (subresource.layerCount == VK_REMAINING_ARRAY_LAYERS)
1242                 resolved.layerCount = testTexture.getArraySize()-subresource.baseArrayLayer;
1243
1244         return resolved;
1245 }
1246
1247 MovePtr<tcu::Texture1DView> getTexture1DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1248 {
1249         DE_ASSERT(subresource.layerCount == 1);
1250
1251         levels.resize(subresource.levelCount);
1252
1253         for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1254         {
1255                 const tcu::ConstPixelBufferAccess& srcLevel = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1256
1257                 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, 0, srcLevel.getWidth(), 1, 1);
1258         }
1259
1260         return MovePtr<tcu::Texture1DView>(new tcu::Texture1DView((int)levels.size(), &levels[0]));
1261 }
1262
1263 MovePtr<tcu::Texture1DArrayView> getTexture1DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1264 {
1265         const TestTexture1D*            tex1D           = dynamic_cast<const TestTexture1D*>(&testTexture);
1266         const TestTexture1DArray*       tex1DArray      = dynamic_cast<const TestTexture1DArray*>(&testTexture);
1267
1268         DE_ASSERT(!!tex1D != !!tex1DArray);
1269         DE_ASSERT(tex1DArray || subresource.baseArrayLayer == 0);
1270
1271         levels.resize(subresource.levelCount);
1272
1273         for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1274         {
1275                 const tcu::ConstPixelBufferAccess& srcLevel = tex1D ? tex1D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1276                                                                                                                         : tex1DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1277
1278                 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, (int)subresource.baseArrayLayer, 0, srcLevel.getWidth(), (int)subresource.layerCount, 1);
1279         }
1280
1281         return MovePtr<tcu::Texture1DArrayView>(new tcu::Texture1DArrayView((int)levels.size(), &levels[0]));
1282 }
1283
1284 MovePtr<tcu::Texture2DView> getTexture2DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1285 {
1286         const TestTexture2D*            tex2D           = dynamic_cast<const TestTexture2D*>(&testTexture);
1287         const TestTexture2DArray*       tex2DArray      = dynamic_cast<const TestTexture2DArray*>(&testTexture);
1288
1289         DE_ASSERT(subresource.layerCount == 1);
1290         DE_ASSERT(!!tex2D != !!tex2DArray);
1291         DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1292
1293         levels.resize(subresource.levelCount);
1294
1295         for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1296         {
1297                 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1298                                                                                                                         : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1299
1300                 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), 1);
1301         }
1302
1303         return MovePtr<tcu::Texture2DView>(new tcu::Texture2DView((int)levels.size(), &levels[0]));
1304 }
1305
1306 MovePtr<tcu::Texture2DArrayView> getTexture2DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1307 {
1308         const TestTexture2D*            tex2D           = dynamic_cast<const TestTexture2D*>(&testTexture);
1309         const TestTexture2DArray*       tex2DArray      = dynamic_cast<const TestTexture2DArray*>(&testTexture);
1310
1311         DE_ASSERT(!!tex2D != !!tex2DArray);
1312         DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1313
1314         levels.resize(subresource.levelCount);
1315
1316         for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1317         {
1318                 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1319                                                                                                                         : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1320
1321                 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1322         }
1323
1324         return MovePtr<tcu::Texture2DArrayView>(new tcu::Texture2DArrayView((int)levels.size(), &levels[0]));
1325 }
1326
1327 MovePtr<tcu::TextureCubeView> getTextureCubeView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1328 {
1329         const static tcu::CubeFace s_faceMap[tcu::CUBEFACE_LAST] =
1330         {
1331                 tcu::CUBEFACE_POSITIVE_X,
1332                 tcu::CUBEFACE_NEGATIVE_X,
1333                 tcu::CUBEFACE_POSITIVE_Y,
1334                 tcu::CUBEFACE_NEGATIVE_Y,
1335                 tcu::CUBEFACE_POSITIVE_Z,
1336                 tcu::CUBEFACE_NEGATIVE_Z
1337         };
1338
1339         const TestTextureCube*          texCube                 = dynamic_cast<const TestTextureCube*>(&testTexture);
1340         const TestTextureCubeArray*     texCubeArray    = dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1341
1342         DE_ASSERT(!!texCube != !!texCubeArray);
1343         DE_ASSERT(subresource.layerCount == 6);
1344         DE_ASSERT(texCubeArray || subresource.baseArrayLayer == 0);
1345
1346         levels.resize(subresource.levelCount*tcu::CUBEFACE_LAST);
1347
1348         for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1349         {
1350                 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1351                 {
1352                         const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray ? texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1353                                                                                                                                            : texCube->getTexture().getLevelFace(levelNdx, s_faceMap[faceNdx]);
1354
1355                         levels[faceNdx*subresource.levelCount + levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer + (texCubeArray ? faceNdx : 0), srcLevel.getWidth(), srcLevel.getHeight(), 1);
1356                 }
1357         }
1358
1359         {
1360                 const tcu::ConstPixelBufferAccess*      reordered[tcu::CUBEFACE_LAST];
1361
1362                 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1363                         reordered[s_faceMap[faceNdx]] = &levels[faceNdx*subresource.levelCount];
1364
1365                 return MovePtr<tcu::TextureCubeView>(new tcu::TextureCubeView((int)subresource.levelCount, reordered));
1366         }
1367 }
1368
1369 MovePtr<tcu::TextureCubeArrayView> getTextureCubeArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1370 {
1371         const TestTextureCubeArray*     texCubeArray    = dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1372
1373         DE_ASSERT(texCubeArray);
1374         DE_ASSERT(subresource.layerCount%6 == 0);
1375
1376         levels.resize(subresource.levelCount);
1377
1378         for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1379         {
1380                 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1381
1382                 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1383         }
1384
1385         return MovePtr<tcu::TextureCubeArrayView>(new tcu::TextureCubeArrayView((int)levels.size(), &levels[0]));
1386 }
1387
1388 MovePtr<tcu::Texture3DView> getTexture3DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1389 {
1390         DE_ASSERT(subresource.baseArrayLayer == 0 && subresource.layerCount == 1);
1391
1392         levels.resize(subresource.levelCount);
1393
1394         for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1395                 levels[levelNdx] = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1396
1397         return MovePtr<tcu::Texture3DView>(new tcu::Texture3DView((int)levels.size(), &levels[0]));
1398 }
1399
1400 bool validateResultImage (const TestTexture&                                    texture,
1401                                                   const VkImageViewType                                 imageViewType,
1402                                                   const VkImageSubresourceRange&                subresource,
1403                                                   const tcu::Sampler&                                   sampler,
1404                                                   const vk::VkComponentMapping&                 componentMapping,
1405                                                   const tcu::ConstPixelBufferAccess&    coordAccess,
1406                                                   const tcu::Vec2&                                              lodBounds,
1407                                                   const tcu::LookupPrecision&                   lookupPrecision,
1408                                                   const tcu::Vec4&                                              lookupScale,
1409                                                   const tcu::Vec4&                                              lookupBias,
1410                                                   const tcu::ConstPixelBufferAccess&    resultAccess,
1411                                                   const tcu::PixelBufferAccess&                 errorAccess)
1412 {
1413         std::vector<tcu::ConstPixelBufferAccess>        levels;
1414
1415         switch (imageViewType)
1416         {
1417                 case VK_IMAGE_VIEW_TYPE_1D:
1418                 {
1419                         UniquePtr<tcu::Texture1DView>                   texView(getTexture1DView(texture, subresource, levels));
1420
1421                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1422                 }
1423
1424                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1425                 {
1426                         UniquePtr<tcu::Texture1DArrayView>              texView(getTexture1DArrayView(texture, subresource, levels));
1427
1428                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1429                 }
1430
1431                 case VK_IMAGE_VIEW_TYPE_2D:
1432                 {
1433                         UniquePtr<tcu::Texture2DView>                   texView(getTexture2DView(texture, subresource, levels));
1434
1435                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1436                 }
1437
1438                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1439                 {
1440                         UniquePtr<tcu::Texture2DArrayView>              texView(getTexture2DArrayView(texture, subresource, levels));
1441
1442                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1443                 }
1444
1445                 case VK_IMAGE_VIEW_TYPE_CUBE:
1446                 {
1447                         UniquePtr<tcu::TextureCubeView>                 texView(getTextureCubeView(texture, subresource, levels));
1448
1449                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1450                 }
1451
1452                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1453                 {
1454                         UniquePtr<tcu::TextureCubeArrayView>    texView(getTextureCubeArrayView(texture, subresource, levels));
1455
1456                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1457                 }
1458
1459                 case VK_IMAGE_VIEW_TYPE_3D:
1460                 {
1461                         UniquePtr<tcu::Texture3DView>                   texView(getTexture3DView(texture, subresource, levels));
1462
1463                         return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1464                 }
1465
1466                 default:
1467                         DE_ASSERT(false);
1468                         return false;
1469         }
1470 }
1471
1472 } // anonymous
1473
1474 tcu::TestStatus ImageSamplingInstance::verifyImage (void)
1475 {
1476         const VkPhysicalDeviceLimits&           limits                                  = m_context.getDeviceProperties().limits;
1477         // \note Color buffer is used to capture coordinates - not sampled texture values
1478         const tcu::TextureFormat                        colorFormat                             (tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1479         const tcu::TextureFormat                        depthStencilFormat;             // Undefined depth/stencil format.
1480         const CoordinateCaptureProgram          coordCaptureProgram;
1481         const rr::Program                                       rrProgram                               = coordCaptureProgram.getReferenceProgram();
1482         ReferenceRenderer                                       refRenderer                             (m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &rrProgram);
1483         const bool                                                      useStencilAspect                = (m_subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT);
1484
1485         bool                                                            compareOkAll                    = true;
1486
1487         tcu::Vec4                                                       lookupScale                             (1.0f);
1488         tcu::Vec4                                                       lookupBias                              (0.0f);
1489
1490         getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, useStencilAspect);
1491
1492         // Render out coordinates
1493         {
1494                 const rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1495                 refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
1496         }
1497
1498         // Verify results
1499         {
1500                 const tcu::Sampler                                      sampler                 = mapVkSampler(m_samplerParams);
1501                 const float                                                     referenceLod    = de::clamp(m_samplerParams.mipLodBias + m_samplerLod, m_samplerParams.minLod, m_samplerParams.maxLod);
1502                 const float                                                     lodError                = 1.0f / static_cast<float>((1u << limits.mipmapPrecisionBits) - 1u);
1503                 const tcu::Vec2                                         lodBounds               (referenceLod - lodError, referenceLod + lodError);
1504                 const vk::VkImageSubresourceRange       subresource             = resolveSubresourceRange(*m_texture, m_subresourceRange);
1505
1506                 const tcu::ConstPixelBufferAccess       coordAccess             = refRenderer.getAccess();
1507                 tcu::TextureLevel                                       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), (int)m_renderSize.x(), (int)m_renderSize.y());
1508                 const tcu::PixelBufferAccess            errorAccess             = errorMask.getAccess();
1509
1510                 const bool                                                      isNearestOnly   = (m_samplerParams.minFilter == VK_FILTER_NEAREST && m_samplerParams.magFilter == VK_FILTER_NEAREST);
1511
1512                 tcu::LookupPrecision                            lookupPrecision;
1513
1514                 // Set precision requirements - very low for these tests as
1515                 // the point of the test is not to validate accuracy.
1516                 lookupPrecision.coordBits               = tcu::IVec3(17, 17, 17);
1517                 lookupPrecision.uvwBits                 = tcu::IVec3(5, 5, 5);
1518                 lookupPrecision.colorMask               = m_componentMask;
1519                 lookupPrecision.colorThreshold  = tcu::computeFixedPointThreshold(max((tcu::IVec4(8, 8, 8, 8) - (isNearestOnly ? 1 : 2)), tcu::IVec4(0))) / swizzleScaleBias(lookupScale, m_componentMapping, 1.0f);
1520
1521                 if (tcu::isSRGB(m_texture->getTextureFormat()))
1522                         lookupPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1523
1524                 de::MovePtr<TestTexture>                        textureCopy;
1525                 TestTexture*                                            texture                 = DE_NULL;
1526
1527                 if (isCombinedDepthStencilType(m_texture->getTextureFormat().type))
1528                 {
1529                         // Verification loop does not support reading from combined depth stencil texture levels.
1530                         // Get rid of stencil component.
1531
1532                         tcu::TextureFormat::ChannelOrder        channelOrder    = tcu::TextureFormat::CHANNELORDER_LAST;
1533                         tcu::TextureFormat::ChannelType         channelType             = tcu::TextureFormat::CHANNELTYPE_LAST;
1534
1535                         if (subresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1536                         {
1537                                 channelOrder    = tcu::TextureFormat::S;
1538                                 channelType             = tcu::TextureFormat::UNSIGNED_INT8;
1539                         }
1540                         else
1541                         {
1542                                 channelOrder = tcu::TextureFormat::D;
1543
1544                                 switch (m_texture->getTextureFormat().type)
1545                                 {
1546                                 case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
1547                                         channelType = tcu::TextureFormat::UNORM_INT16;
1548                                         break;
1549                                 case tcu::TextureFormat::UNSIGNED_INT_24_8:
1550                                 case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
1551                                         channelType = tcu::TextureFormat::UNORM_INT24;
1552                                         break;
1553                                 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1554                                         channelType = tcu::TextureFormat::FLOAT;
1555                                         break;
1556                                 default:
1557                                         DE_FATAL("Unhandled texture format type in switch");
1558                                 }
1559                         }
1560
1561                         textureCopy     = m_texture->copy(tcu::TextureFormat(channelOrder, channelType));
1562                         texture         = textureCopy.get();
1563                 }
1564                 else
1565                 {
1566                         texture         = m_texture.get();
1567                 }
1568
1569                 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1570                 {
1571                         // Read back result image
1572                         UniquePtr<tcu::TextureLevel>            result                  (readColorAttachment(m_context.getDeviceInterface(),
1573                                                                                                                                                                          m_context.getDevice(),
1574                                                                                                                                                                          m_context.getUniversalQueue(),
1575                                                                                                                                                                          m_context.getUniversalQueueFamilyIndex(),
1576                                                                                                                                                                          m_context.getDefaultAllocator(),
1577                                                                                                                                                                          **m_colorImages[imgNdx],
1578                                                                                                                                                                          m_colorFormat,
1579                                                                                                                                                                          m_renderSize));
1580                         const tcu::ConstPixelBufferAccess       resultAccess    = result->getAccess();
1581                         bool                                                            compareOk               = validateResultImage(*texture,
1582                                                                                                                                                                           m_imageViewType,
1583                                                                                                                                                                           subresource,
1584                                                                                                                                                                           sampler,
1585                                                                                                                                                                           m_componentMapping,
1586                                                                                                                                                                           coordAccess,
1587                                                                                                                                                                           lodBounds,
1588                                                                                                                                                                           lookupPrecision,
1589                                                                                                                                                                           lookupScale,
1590                                                                                                                                                                           lookupBias,
1591                                                                                                                                                                           resultAccess,
1592                                                                                                                                                                           errorAccess);
1593                         if (!compareOk)
1594                                 m_context.getTestContext().getLog()
1595                                 << tcu::TestLog::Image("Result", "Result Image", resultAccess)
1596                                 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorAccess);
1597
1598                         compareOkAll = compareOkAll && compareOk;
1599                 }
1600         }
1601
1602         if (compareOkAll)
1603                 return tcu::TestStatus::pass("Result image matches reference");
1604         else
1605                 return tcu::TestStatus::fail("Image mismatch");
1606 }
1607
1608 } // pipeline
1609 } // vkt