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