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