Merge vk-gl-cts/vulkan-cts-1.3.2 into vk-gl-cts/main
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageSampleCompressedTextureTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021-2022 Google LLC.
6  *
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 Tests that images using a block-compressed format are sampled
23  * correctly
24  *
25  * These tests create a storage image using a 128-bit or a 64-bit
26  * block-compressed image format and an ImageView using an uncompressed
27  * format. Each test case then fills the storage image with compressed
28  * color values in a compute shader and samples the storage image. If the
29  * sampled values are pure blue, the test passes.
30  *//*--------------------------------------------------------------------*/
31
32 #include "deUniquePtr.hpp"
33 #include "deStringUtil.hpp"
34
35 #include "tcuCompressedTexture.hpp"
36 #include "tcuVectorType.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuTexture.hpp"
40
41 #include "vkDefs.hpp"
42 #include "vkRef.hpp"
43 #include "vkRefUtil.hpp"
44 #include "vkPrograms.hpp"
45 #include "vkMemUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vkImageUtil.hpp"
48 #include "vkCmdUtil.hpp"
49 #include "vkObjUtil.hpp"
50 #include "vkTypeUtil.hpp"
51 #include "vkImageWithMemory.hpp"
52 #include "vktImageTestsUtil.hpp"
53 #include "vkBarrierUtil.hpp"
54
55 #include "vktTestCaseUtil.hpp"
56 #include "tcuTestLog.hpp"
57
58 #include <string>
59
60 using namespace vk;
61
62 namespace vkt
63 {
64 namespace image
65 {
66 namespace
67 {
68 using tcu::IVec3;
69 using tcu::Vec2;
70 using tcu::Vec4;
71 using std::vector;
72 using de::MovePtr;
73 using tcu::TextureLevel;
74 using tcu::PixelBufferAccess;
75 using tcu::ConstPixelBufferAccess;
76
77 const VkDeviceSize      BUFFERSIZE      = 100u * 1024;
78 const int                       WIDTH           = 80;
79 const int                       HEIGHT          = 80;
80 const int                       FACES           = 6;
81
82 inline VkImageCreateInfo makeImageCreateInfo (const IVec3& size, const VkFormat& format, bool storageImage, bool cubemap)
83 {
84         VkImageUsageFlags       usageFlags      = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
85                                                                           | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
86         VkImageCreateFlags      createFlags     = cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : DE_NULL;
87         const deUint32          layerCount      = cubemap ? 6u : 1u;
88
89         if (storageImage)
90         {
91                 usageFlags      = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
92                                           | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
93                 createFlags     |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
94                                           | VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
95         }
96
97         const VkImageCreateInfo imageParams     =
98         {
99                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    //  VkStructureType         sType;
100                 DE_NULL,                                                                //  const void*             pNext;
101                 createFlags,                                                    //  VkImageCreateFlags      flags;
102                 VK_IMAGE_TYPE_2D,                                               //  VkImageType             imageType;
103                 format,                                                                 //  VkFormat                format;
104                 makeExtent3D(size.x(), size.y(), 1u),   //  VkExtent3D              extent;
105                 1u,                                                                             //  deUint32                mipLevels;
106                 layerCount,                                                             //  deUint32                arrayLayers;
107                 VK_SAMPLE_COUNT_1_BIT,                                  //  VkSampleCountFlagBits   samples;
108                 VK_IMAGE_TILING_OPTIMAL,                                //  VkImageTiling           tiling;
109                 usageFlags,                                                             //  VkImageUsageFlags       usage;
110                 VK_SHARING_MODE_EXCLUSIVE,                              //  VkSharingMode           sharingMode;
111                 0u,                                                                             //  deUint32                queueFamilyIndexCount;
112                 DE_NULL,                                                                //  const deUint32*         pQueueFamilyIndices;
113                 VK_IMAGE_LAYOUT_UNDEFINED,                              //  VkImageLayout           initialLayout;
114         };
115
116         return imageParams;
117 }
118
119 Move<VkBuffer> makeVertexBuffer (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
120 {
121         const VkBufferCreateInfo        vertexBufferParams =
122         {
123                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType      sType;
124                 DE_NULL,                                                                // const void*          pNext;
125                 0u,                                                                             // VkBufferCreateFlags  flags;
126                 BUFFERSIZE,                                                             // VkDeviceSize         size;
127                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              // VkBufferUsageFlags   usage;
128                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode        sharingMode;
129                 1u,                                                                             // deUint32             queueFamilyIndexCount;
130                 &queueFamilyIndex                                               // const deUint32*      pQueueFamilyIndices;
131         };
132
133         Move<VkBuffer>                          vertexBuffer            = createBuffer(vk, device, &vertexBufferParams);
134         return vertexBuffer;
135 }
136
137 class SampleDrawnTextureTestInstance : public TestInstance
138 {
139 public:
140         SampleDrawnTextureTestInstance (Context&                        context,
141                                                                         const VkFormat  imageFormat,
142                                                                         const VkFormat  imageViewFormat,
143                                                                         const bool              twoSamplers,
144                                                                         const bool              cubemap);
145
146         tcu::TestStatus iterate                 (void);
147
148 private:
149         const VkFormat  m_imageFormat;
150         const VkFormat  m_imageViewFormat;
151         const bool              m_twoSamplers;
152         const bool              m_cubemap;
153 };
154
155 SampleDrawnTextureTestInstance::SampleDrawnTextureTestInstance (Context& context, const VkFormat imageFormat, const VkFormat imageViewFormat,
156                                                                                                                                 const bool twoSamplers, const bool cubemap)
157         : TestInstance                                                                                     (context)
158         , m_imageFormat         (imageFormat)
159         , m_imageViewFormat     (imageViewFormat)
160         , m_twoSamplers         (twoSamplers)
161         , m_cubemap                     (cubemap)
162 {
163 }
164
165 template<typename T>
166 inline size_t sizeInBytes (const vector<T>& vec)
167 {
168         return vec.size() * sizeof(vec[0]);
169 }
170
171 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice& device)
172 {
173         const VkSamplerCreateInfo samplerParams =
174         {
175                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType          sType;
176                 DE_NULL,                                                                        // const void*              pNext;
177                 (VkSamplerCreateFlags)0,                                        // VkSamplerCreateFlags     flags;
178                 VK_FILTER_NEAREST,                                                      // VkFilter                 magFilter;
179                 VK_FILTER_NEAREST,                                                      // VkFilter                 minFilter;
180                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode      mipmapMode;
181                 VK_SAMPLER_ADDRESS_MODE_REPEAT,                         // VkSamplerAddressMode     addressModeU;
182                 VK_SAMPLER_ADDRESS_MODE_REPEAT,                         // VkSamplerAddressMode     addressModeV;
183                 VK_SAMPLER_ADDRESS_MODE_REPEAT,                         // VkSamplerAddressMode     addressModeW;
184                 0.0f,                                                                           // float                    mipLodBias;
185                 VK_FALSE,                                                                       // VkBool32                 anisotropyEnable;
186                 1.0f,                                                                           // float                    maxAnisotropy;
187                 VK_FALSE,                                                                       // VkBool32                 compareEnable;
188                 VK_COMPARE_OP_ALWAYS,                                           // VkCompareOp              compareOp;
189                 0.0f,                                                                           // float                    minLod;
190                 0.0f,                                                                           // float                    maxLod;
191                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,        // VkBorderColor            borderColor;
192                 VK_FALSE,                                                                       // VkBool32                 unnormalizedCoordinates;
193         };
194
195         return createSampler(vk, device, &samplerParams);
196 }
197
198 struct Vertex
199 {
200         Vertex(Vec4 position_, Vec2 uv_) : position(position_), uv(uv_) {}
201         Vec4 position;
202         Vec2 uv;
203
204         static VkVertexInputBindingDescription                          getBindingDescription           (void);
205         static vector<VkVertexInputAttributeDescription>        getAttributeDescriptions        (void);
206 };
207
208 VkVertexInputBindingDescription Vertex::getBindingDescription (void)
209 {
210         static const VkVertexInputBindingDescription desc =
211         {
212                 0u,                                                                             // deUint32             binding;
213                 static_cast<deUint32>(sizeof(Vertex)),  // deUint32             stride;
214                 VK_VERTEX_INPUT_RATE_VERTEX,                    // VkVertexInputRate    inputRate;
215         };
216
217         return desc;
218 }
219
220 vector<VkVertexInputAttributeDescription> Vertex::getAttributeDescriptions (void)
221 {
222         static const vector<VkVertexInputAttributeDescription> desc =
223         {
224                 {
225                         0u,                                                                                                     // deUint32    location;
226                         0u,                                                                                                     // deUint32    binding;
227                         vk::VK_FORMAT_R32G32B32A32_SFLOAT,                                      // VkFormat    format;
228                         static_cast<deUint32>(offsetof(Vertex, position)),      // deUint32    offset;
229                 },
230                 {
231                         1u,                                                                                                     // deUint32    location;
232                         0u,                                                                                                     // deUint32    binding;
233                         vk::VK_FORMAT_R32G32_SFLOAT,                                            // VkFormat    format;
234                         static_cast<deUint32>(offsetof(Vertex, uv)),            // deUint32    offset;
235                 },
236         };
237
238         return desc;
239 }
240
241 // Generates the vertices of a full quad and texture coordinates of each vertex.
242 vector<Vertex> generateVertices (void)
243 {
244         vector<Vertex> vertices;
245         vertices.push_back(Vertex(Vec4(-1.0f, -1.0f, 0.0f, 1.0f), Vec2(0.0f, 0.0f)));
246         vertices.push_back(Vertex(Vec4( 1.0f, -1.0f, 0.0f, 1.0f), Vec2(1.0f, 0.0f)));
247         vertices.push_back(Vertex(Vec4(-1.0f,  1.0f, 0.0f, 1.0f), Vec2(0.0f, 1.0f)));
248         vertices.push_back(Vertex(Vec4( 1.0f, -1.0f, 0.0f, 1.0f), Vec2(1.0f, 0.0f)));
249         vertices.push_back(Vertex(Vec4( 1.0f,  1.0f, 0.0f, 1.0f), Vec2(1.0f, 1.0f)));
250         vertices.push_back(Vertex(Vec4(-1.0f,  1.0f, 0.0f, 1.0f), Vec2(0.0f, 1.0f)));
251
252         return vertices;
253 }
254
255 // Generates a reference image filled with pure blue.
256 TextureLevel makeReferenceImage (const VkFormat format, int width, int height)
257 {
258         TextureLevel referenceImage(mapVkFormat(format), width, height, 1);
259         for (int y = 0; y < height; y++)
260                 for (int x = 0; x < width; x++)
261                         referenceImage.getAccess().setPixel(tcu::IVec4(0, 0, 255, 255), x, y, 0);
262
263         return referenceImage;
264 }
265
266 tcu::TestStatus SampleDrawnTextureTestInstance::iterate (void)
267 {
268         DE_ASSERT(m_imageFormat == VK_FORMAT_BC1_RGB_UNORM_BLOCK || m_imageFormat == VK_FORMAT_BC3_UNORM_BLOCK);
269
270         const DeviceInterface&                  vk                                              = m_context.getDeviceInterface();
271         const VkDevice                                  device                                  = m_context.getDevice();
272         Allocator&                                              allocator                               = m_context.getDefaultAllocator();
273         const VkQueue                                   queue                                   = m_context.getUniversalQueue();
274         const deUint32                                  queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
275
276         const IVec3                                             imageSize                               = {static_cast<int>(WIDTH), HEIGHT, 1};
277         const VkExtent2D                                renderSize                              = {deUint32(WIDTH), deUint32(HEIGHT)};
278         const VkRect2D                                  renderArea                              = makeRect2D(makeExtent3D(WIDTH, HEIGHT, 1u));
279         const vector<VkRect2D>                  scissors                                (1u, renderArea);
280         const vector<VkViewport>                viewports                               (1u, makeViewport(makeExtent3D(WIDTH, HEIGHT, 1u)));
281
282         const Move<VkCommandPool>               cmdPool                                 = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
283         const Move<VkCommandBuffer>             cmdBuffer                               = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
284
285         const Unique<VkDescriptorPool>  descriptorPool                  (DescriptorPoolBuilder()
286                                                                                                                          .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 6)
287                                                                                                                          .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 12)
288                                                                                                                          .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 21u));
289
290         const VkFormat                                  renderedImageFormat             = VK_FORMAT_R8G8B8A8_UNORM;
291         tcu::CompressedTexFormat                compressedFormat                (mapVkCompressedFormat(m_imageFormat));
292         IVec3                                                   blockSize                               = tcu::getBlockPixelSize(compressedFormat);
293
294         DE_ASSERT(blockSize.z() == 1);
295
296         IVec3                                                   storageImageViewSize = imageSize / blockSize;
297
298         // Create a storage image. The first pipeline fills it and the second pipeline
299         // uses it as a sampling source.
300         const VkImageCreateInfo                 imageCreateInfo                 = makeImageCreateInfo(imageSize, m_imageFormat, true, m_cubemap);
301         const VkImageSubresourceRange   imageSubresourceRange   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1);
302         const ImageWithMemory                   storageImage                    (vk, device, m_context.getDefaultAllocator(), imageCreateInfo, MemoryRequirement::Any);
303
304         // Create image views and descriptor sets for the first pipeline
305         Move<VkDescriptorSetLayout>             descriptorSetLayout             = DescriptorSetLayoutBuilder()
306                         .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
307                         .build(vk, device);
308
309         Move<VkImageView>                               storageImageImageView;
310         VkDescriptorImageInfo                   storageImageDscrInfo;
311         Move<VkDescriptorSet>                   storageImageDescriptorSet;
312
313         // Cubemap tests use separate image views for each side of a cubemap.
314         vector<VkImageSubresourceRange> cubeSubresourceRanges;
315         vector<Move<VkImageView>>               cubeStorageImageViews;
316         vector<VkDescriptorImageInfo>   cubeStorageDscrImageInfos;
317         vector<Move<VkDescriptorSet>>   cubeStorageDscrSets;
318
319         if (m_cubemap)
320         {
321                 DescriptorSetUpdateBuilder updateBuilder;
322                 for (int i = 0; i < FACES; i++)
323                 {
324                         cubeSubresourceRanges.emplace_back(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, i, 1));
325                         cubeStorageImageViews.emplace_back(makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, cubeSubresourceRanges[i]));
326                         cubeStorageDscrImageInfos.emplace_back(makeDescriptorImageInfo(DE_NULL, *cubeStorageImageViews[i], VK_IMAGE_LAYOUT_GENERAL));
327                         cubeStorageDscrSets.emplace_back(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
328                         updateBuilder.writeSingle(*cubeStorageDscrSets[i], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &cubeStorageDscrImageInfos[i]);
329                 }
330                 updateBuilder.update(vk, device);
331         }
332         else
333         {
334                 storageImageImageView           = makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, imageSubresourceRange);
335                 storageImageDscrInfo            = makeDescriptorImageInfo(DE_NULL, *storageImageImageView, VK_IMAGE_LAYOUT_GENERAL);
336                 storageImageDescriptorSet       = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
337
338                 DescriptorSetUpdateBuilder()
339                         .writeSingle(*storageImageDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImageDscrInfo)
340                         .update(vk, device);
341         }
342
343         // Create a compute pipeline.
344         Move<VkShaderModule>                    computeShader                   = createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u);
345         const VkPushConstantRange               pushConstantRange               =
346         {
347                 VK_SHADER_STAGE_COMPUTE_BIT,    // VkShaderStageFlags    stageFlags;
348                 0u,                                                             // uint32_t              offset;
349                 (deUint32)sizeof(deUint32),             // uint32_t              size;
350         };
351
352         const Move<VkPipelineLayout>    computePipelineLayout   = makePipelineLayout(vk, device, 1, &(*descriptorSetLayout), 1, &pushConstantRange);
353         Move<VkPipeline>                                computePipeline                 = makeComputePipeline(vk, device, *computePipelineLayout, *computeShader);
354
355
356         // Create a graphics pipeline and all the necessary components for sampling the storage image
357
358         // The first sampler uses an uncompressed format.
359         const Unique<VkSampler>                 sampler                                 (makeSampler(vk, device));
360
361         // The second sampler uses the same format as the image.
362         const Unique<VkSampler>                 sampler2                                (makeSampler(vk, device));
363
364         // Image views implicitly derive the usage flags from the image. Drop the storage image flag since it's incompatible
365         // with the compressed format and unnecessary in sampling.
366         VkImageUsageFlags                               usageFlags                              = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
367         VkImageViewUsageCreateInfo              imageViewUsageInfo              =
368         {
369                 VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,         //VkStructureType               sType;
370                 DE_NULL,                                                                                        //const void*                   pNext;
371                 usageFlags,                                                                                     //VkImageUsageFlags             usage;
372         };
373
374         Move<VkImageView>                               sampledImageView;
375         Move<VkImageView>                               sampledImageView2;
376         VkDescriptorImageInfo                   samplerDscrImageInfo;
377         VkDescriptorImageInfo                   samplerDscrImageInfo2;
378         Move<VkDescriptorSet>                   graphicsDescriptorSet;
379
380         // Cubemap tests use separate image views for each side of a cubemap.
381         vector<Move<VkImageView>>               cubeSamplerImageViews;
382         vector<Move<VkImageView>>               cubeSampler2ImageViews;
383         vector<VkDescriptorImageInfo>   cubeSamplerDscrImageInfos;
384         vector<VkDescriptorImageInfo>   cubeSampler2DscrImageInfos;
385         vector<Move<VkDescriptorSet>>   cubeSamplerDescriptorSets;
386
387         const auto                                              graphicsDscrSetLayout   (DescriptorSetLayoutBuilder()
388                                                                                         .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &sampler2.get())
389                                                                                         .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &sampler.get())
390                                                                                         .build(vk, device));
391
392         if (m_cubemap)
393         {
394                 DescriptorSetUpdateBuilder updateBuilder;
395                 for (int i = 0; i < FACES; i++)
396                 {
397                         cubeSamplerImageViews.emplace_back(makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageFormat, cubeSubresourceRanges[i], &imageViewUsageInfo));
398                         cubeSamplerDscrImageInfos.emplace_back(makeDescriptorImageInfo(sampler2.get(), *cubeSamplerImageViews[i], VK_IMAGE_LAYOUT_GENERAL));
399                         cubeSamplerDescriptorSets.emplace_back(makeDescriptorSet(vk, device, *descriptorPool, *graphicsDscrSetLayout));
400                         updateBuilder.writeSingle(*cubeSamplerDescriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &cubeSamplerDscrImageInfos[i]);
401                 }
402
403                 if (m_twoSamplers)
404                 {
405                         for (int i = 0; i < FACES; i++)
406                         {
407                                 cubeSampler2ImageViews.emplace_back(makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, cubeSubresourceRanges[i]));
408                                 cubeSampler2DscrImageInfos.emplace_back(makeDescriptorImageInfo(sampler.get(), *cubeSampler2ImageViews[i], VK_IMAGE_LAYOUT_GENERAL));
409                                 updateBuilder.writeSingle(*cubeSamplerDescriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &cubeSampler2DscrImageInfos[i]);
410                         }
411                 }
412                 updateBuilder.update(vk, device);
413         }
414         else
415         {
416                 const VkImageSubresourceRange   subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1);
417                 DescriptorSetUpdateBuilder              updateBuilder;
418
419                 sampledImageView2 = makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageFormat, subresourceRange, &imageViewUsageInfo);
420                 samplerDscrImageInfo2 = makeDescriptorImageInfo(sampler2.get(), *sampledImageView2, VK_IMAGE_LAYOUT_GENERAL);
421                 graphicsDescriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *graphicsDscrSetLayout);
422
423                 if (m_twoSamplers)
424                 {
425                         sampledImageView = makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_imageViewFormat, subresourceRange);
426                         samplerDscrImageInfo = makeDescriptorImageInfo(sampler.get(), *sampledImageView, VK_IMAGE_LAYOUT_GENERAL);
427                 }
428
429                 updateBuilder.writeSingle(*graphicsDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &samplerDscrImageInfo2);
430                 if (m_twoSamplers)
431                         updateBuilder.writeSingle(*graphicsDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &samplerDscrImageInfo);
432
433                 updateBuilder.update(vk, device);
434         }
435
436         // Sampled values will be rendered on this image.
437         const VkImageSubresourceRange   targetSubresourceRange  = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1);
438         const VkImageCreateInfo                 targetImageCreateInfo   = makeImageCreateInfo(imageSize, renderedImageFormat, false, false);
439
440         const ImageWithMemory                   targetImage                             (vk, device, m_context.getDefaultAllocator(), targetImageCreateInfo, MemoryRequirement::Any);
441         Move<VkImageView>                               targetImageView                 = makeImageView(vk, device, *targetImage, VK_IMAGE_VIEW_TYPE_2D, renderedImageFormat, targetSubresourceRange);
442
443         // Clear the render target image as black and do a layout transition.
444         clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), targetImage.get(),
445                                         Vec4(0, 0, 0, 0), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
446
447         const VkPushConstantRange               pushConstantRange2              =
448         {
449                 VK_SHADER_STAGE_FRAGMENT_BIT,   // VkShaderStageFlags    stageFlags;
450                 0u,                                                             // uint32_t              offset;
451                 (deUint32)sizeof(deUint32),             // uint32_t              size;
452         };
453
454         const Move<VkPipelineLayout>    graphicsPipelineLayout  = makePipelineLayout(vk, device, 1, &(*graphicsDscrSetLayout), 1, &pushConstantRange2);
455
456         // Vertices for a full quad and texture coordinates for each vertex.
457         const vector<Vertex>                    vertices                                = generateVertices();
458         Move<VkBuffer>                                  vertexBuffer                    = makeVertexBuffer(vk, device, queueFamilyIndex);
459         de::MovePtr<Allocation>                 vertexBufferAlloc               = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
460         const VkDeviceSize                              vertexBufferOffset              = 0ull;
461         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], sizeInBytes(vertices));
462         flushAlloc(vk, device, *vertexBufferAlloc);
463
464         const auto                                              vtxBindingDescription   = Vertex::getBindingDescription();
465         const auto                                              vtxAttrDescriptions             = Vertex::getAttributeDescriptions();
466
467         const VkPipelineVertexInputStateCreateInfo vtxInputInfo =
468         {
469                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                             sType
470                 nullptr,                                                                                                        // const void*                                 pNext
471                 0u,                                                                                                                     // VkPipelineVertexInputStateCreateFlags       flags
472                 1u,                                                                                                                     // deUint32                                    vertexBindingDescriptionCount
473                 &vtxBindingDescription,                                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
474                 static_cast<deUint32>(vtxAttrDescriptions.size()),                      // deUint32                                    vertexAttributeDescriptionCount
475                 vtxAttrDescriptions.data(),                                                                     // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
476         };
477
478         Move<VkShaderModule>                    vertexShader                    = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
479         Move<VkShaderModule>                    fragmentShader                  = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
480
481         // Create a render pass, a framebuffer, and the second pipeline.
482         Move<VkRenderPass>                              renderPass                              = makeRenderPass(vk, device, renderedImageFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD,
483                                                                                                                                                          VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
484         Move<VkFramebuffer>                             framebuffer                             = makeFramebuffer(vk, device, *renderPass, targetImageView.get(), renderSize.width, renderSize.height);
485         const Move<VkPipeline>                  graphicsPipeline                = makeGraphicsPipeline(vk, device, graphicsPipelineLayout.get(), vertexShader.get(), DE_NULL,
486                                                                                                                                                                    DE_NULL, DE_NULL, fragmentShader.get(), renderPass.get(), viewports, scissors,
487                                                                                                                                                                    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vtxInputInfo);
488
489         // Create a result buffer.
490         const VkBufferCreateInfo                resultBufferCreateInfo  = makeBufferCreateInfo(BUFFERSIZE, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
491         Move<VkBuffer>                                  resultBuffer                    = createBuffer(vk, device, &resultBufferCreateInfo);
492         MovePtr<Allocation>                             resultBufferMemory              = allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible);
493         TextureLevel                                    resultImage                             (mapVkFormat(renderedImageFormat), renderSize.width, renderSize.height, 1);
494         VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
495
496         // Generate a reference image.
497         TextureLevel                                    expectedImage                   = makeReferenceImage(renderedImageFormat, WIDTH, HEIGHT);
498
499         beginCommandBuffer(vk, *cmdBuffer);
500
501         // Do a layout transition for the storage image.
502         const VkImageSubresourceRange   imageSubresourceRange2  = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, m_cubemap ? 6 : 1);
503         const auto                                              barrier1                                = makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
504                                                                                                                                                                          VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
505                                                                                                                                                                          storageImage.get(), imageSubresourceRange2);
506         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier1);
507
508         // Bind the vertices and the descriptors used in the graphics pipeline.
509         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
510
511         // Fill the storage image and sample it twice.
512         for (int pass = 0; pass < 2; pass++)
513         {
514                 // If both samplers are enabled, it's not necessary to run the compute shader twice since it already writes
515                 // the expected values on the first pass. The first sampler uses an uncompressed image format so the result
516                 // image will contain garbage if the second sampler doesn't work properly.
517                 if (!m_twoSamplers || pass == 0)
518                 {
519                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
520                         vk.cmdPushConstants(*cmdBuffer, *computePipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(deInt32), &pass);
521
522                         // If cubemaps are enabled, loop over six times and bind the next face of the cubemap image on each iteration.
523                         if (m_cubemap)
524                         {
525                                 for (int face = 0; face < FACES; face++)
526                                 {
527                                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &(cubeStorageDscrSets[face].get()), 0u, DE_NULL);
528                                         vk.cmdDispatch(*cmdBuffer, storageImageViewSize.x(), storageImageViewSize.y(), 1u);
529                                 }
530                         }
531                         else
532                         {
533                                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &storageImageDescriptorSet.get(), 0u, DE_NULL);
534                                 vk.cmdDispatch(*cmdBuffer, storageImageViewSize.x(), storageImageViewSize.y(), 1u);
535                         }
536
537                         const auto barrier2 = makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
538                                                                                                                  VK_IMAGE_LAYOUT_GENERAL, storageImage.get(), imageSubresourceRange);
539                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier2);
540                 }
541
542                 vk.cmdPushConstants(*cmdBuffer, *graphicsPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &pass);
543
544                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
545
546                 // If cubemaps are enabled, loop over six times and bind the next face of the cubemap image on each iteration.
547                 if (m_cubemap)
548                 {
549                         for (int face = 0; face < FACES; face++)
550                         {
551                                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0u, 1u, &(cubeSamplerDescriptorSets[face].get()), 0u, DE_NULL);
552
553                                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, imageSize.x(), imageSize.y()),0u, DE_NULL);
554                                 vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
555                                 endRenderPass(vk, *cmdBuffer);
556
557                                 if (face < FACES-1)
558                                 {
559                                         const auto barrier4 = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
560                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
561                                                                                                                                  targetImage.get(), targetSubresourceRange);
562                                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
563                                                                                   0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier4);
564                                 }
565                         }
566                 }
567                 else
568                 {
569                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0u, 1u, &(graphicsDescriptorSet.get()), 0u, DE_NULL);
570
571                         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, imageSize.x(), imageSize.y()),0u, DE_NULL);
572                         vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
573                         endRenderPass(vk, *cmdBuffer);
574                 }
575
576                 if (pass == 0)
577                 {
578                         const auto barrier3 = makeImageMemoryBarrier(VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL,
579                                                                                                                  VK_IMAGE_LAYOUT_GENERAL, storageImage.get(), imageSubresourceRange);
580                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier3);
581
582                         const auto barrier4 = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
583                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
584                                                                                                                  targetImage.get(), targetSubresourceRange);
585                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u, &barrier4);
586                 }
587         }
588
589         // Copy the sampled values from the target image into the result image.
590         copyImageToBuffer(vk, *cmdBuffer, *targetImage, *resultBuffer, tcu::IVec2(WIDTH, HEIGHT), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
591
592         endCommandBuffer(vk, *cmdBuffer);
593         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
594
595         invalidateAlloc(vk, device, *resultBufferMemory);
596
597         clear(resultImage.getAccess(), tcu::IVec4(0));
598         copy(resultImage.getAccess(), ConstPixelBufferAccess(resultImage.getFormat(), resultImage.getSize(), resultBufferMemory->getHostPtr()));
599
600         bool                                                    result                                  = true;
601
602         if (m_cubemap)
603         {
604                 // The first pass draws pure red on the faces and the second pass redraws them with pure blue.
605                 // Sampling anywhere should produce colors with a 0.0 red component and > 0.0 blue and alpha components.
606                 for (deUint32 y = 0; y < renderSize.height; y++)
607                 {
608                         for (deUint32 x = 0; x < renderSize.width; x++)
609                         {
610                                 const deUint8* ptr = static_cast<const deUint8 *>(resultImage.getAccess().getPixelPtr(x, y, 0));
611                                 const tcu::IVec4 val = tcu::IVec4(ptr[0], ptr[1], ptr[2], ptr[3]);
612                                 if (!(val[0] == 0 && val[2] > 0 && val[3] > 0))
613                                         result = false;
614                         }
615                 }
616
617                 // Log attachment contents.
618                 m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Attachment ", "")
619                                                                                         << tcu::TestLog::Image("Rendered image", "Rendered image", resultImage.getAccess())
620                                                                                         << tcu::TestLog::EndImageSet;
621         }
622         else
623         {
624                 // Each test case should render pure blue as the result.
625                 result = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Image Comparison", "",
626                                                                                         expectedImage.getAccess(), resultImage.getAccess(),
627                                                                                         tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
628         }
629
630         if (result)
631                 return tcu::TestStatus::pass("pass");
632         else
633                 return tcu::TestStatus::fail("fail");
634 }
635
636 class SampleDrawnTextureTest : public TestCase
637 {
638 public:
639                                                 SampleDrawnTextureTest  (tcu::TestContext&      testCtx,
640                                                                                                  const std::string&     name,
641                                                                                                  const std::string&     description,
642                                                                                                  const VkFormat         imageFormat,
643                                                                                                  const VkFormat         imageViewFormat,
644                                                                                                  const bool                     twoSamplers,
645                                                                                                  const bool                     cubemap);
646
647         void                            initPrograms                    (SourceCollections& programCollection) const;
648         TestInstance*           createInstance                  (Context&                       context) const;
649         virtual void            checkSupport                    (Context& context) const;
650
651 private:
652         const VkFormat          m_imageFormat;
653         const VkFormat          m_imageViewFormat;
654         const bool                      m_twoSamplers;
655         const bool                      m_cubemap;
656 };
657
658 SampleDrawnTextureTest::SampleDrawnTextureTest (tcu::TestContext&       testCtx,
659                                                                                                 const std::string&      name,
660                                                                                                 const std::string&      description,
661                                                                                                 const VkFormat          imageFormat,
662                                                                                                 const VkFormat          imageViewFormat,
663                                                                                                 const bool                      twoSamplers,
664                                                                                                 const bool                      cubemap)
665         : TestCase      (testCtx, name, description)
666         , m_imageFormat (imageFormat)
667         , m_imageViewFormat     (imageViewFormat)
668         , m_twoSamplers (twoSamplers)
669         , m_cubemap (cubemap)
670 {
671 }
672
673 void SampleDrawnTextureTest::checkSupport(Context& context) const
674 {
675         const auto&                             vki                                     = context.getInstanceInterface();
676         const auto                              usageFlags                      = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
677                                                                                                   | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
678         auto                                    creationFlags           = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
679                                                                                                   | VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
680         if (m_cubemap)
681                 creationFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
682
683         // Check that:
684         // - VkImageViewUsageCreateInfo can be used to override implicit usage flags derived from the image.
685         // - A compressed image can be created with usage flags that are not supported for the format but are
686         //   supported by an image view that is using uncompressed format where each texel corresponds to
687         //   a compressed texel block of the image.
688
689         if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance2"))
690                 TCU_THROW(NotSupportedError, "Device does not support extended image usage flags nor overriding implicit usage flags");
691
692         VkImageFormatProperties imageFormatProperties;
693
694         if (vki.getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), m_imageFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
695                                                                                                    usageFlags, creationFlags, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
696         {
697                 std::string     algorithmName   = (m_imageFormat == vk::VK_FORMAT_BC3_UNORM_BLOCK) ?  "BC3" : "BC1";
698                 std::string     errorMsg                = algorithmName;
699
700                 errorMsg += m_cubemap ? " compressed cubemap images" : " compressed images";
701                 errorMsg += " created with VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT";
702                 errorMsg += " and VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT flags not supported.";
703                 TCU_THROW(NotSupportedError, errorMsg);
704         }
705 }
706
707 void SampleDrawnTextureTest::initPrograms (SourceCollections& programCollection) const
708 {
709         // Pure red, green, and blue compressed with the BC1 and BC3 algorithms.
710         std::string                                     bc1_red                         = "uvec4(4160813056u, 0u, 4160813056u, 0u);\n";
711         std::string                                     bc1_blue                        = "uvec4(2031647, 0u, 2031647, 0u);\n";
712         std::string                                     bc3_red                         = "uvec4(4294967295u, 4294967295u, 4160813056u, 0u);\n";
713         std::string                                     bc3_blue                        = "uvec4(4294967295u, 4294967295u, 2031647, 0u);\n";
714
715         std::string                                     red                                     = (m_imageFormat == VK_FORMAT_BC1_RGB_UNORM_BLOCK) ? bc1_red : bc3_red;
716         std::string                                     blue                            = (m_imageFormat == VK_FORMAT_BC1_RGB_UNORM_BLOCK) ? bc1_blue : bc3_blue;
717
718         std::ostringstream                      computeSrc;
719
720         // Generate the compute shader.
721         computeSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
722         computeSrc << "layout(set = 0, binding = 0, rgba32ui) uniform highp uimage2D img;\n";
723         computeSrc << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
724
725         if (!m_twoSamplers)
726         {
727                 computeSrc
728                         << "layout(push_constant) uniform constants {\n"
729                         << "    int pass;\n"
730                         << "} pc;\n";
731         }
732
733         computeSrc << "void main() {\n";
734
735         if (m_twoSamplers)
736                 computeSrc << "    uvec4 color = " << blue;
737         else
738         {
739                 computeSrc << "    uvec4 color = " << red;
740                 computeSrc << "    if (pc.pass == 1)\n";
741                 computeSrc << "        color = " << blue;
742         }
743
744         computeSrc
745         << "    imageStore(img, ivec2(gl_GlobalInvocationID.xy), color);\n"
746         << "}\n";
747
748         // Generate the vertex shader.
749         std::ostringstream                      vertexSrc;
750         vertexSrc
751                 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
752                 << "layout(location = 0) in highp vec4 a_position;\n"
753                 << "layout(location = 1) in vec2 inTexCoord;\n"
754                 << "layout(location = 1) out vec2 fragTexCoord;\n"
755                 << "void main (void) {\n"
756                 << "    gl_Position = a_position;\n"
757                 << "    fragTexCoord = inTexCoord;\n"
758                 << "}\n";
759
760         // Generate the fragment shader.
761         std::ostringstream                      fragmentSrc;
762         fragmentSrc
763                 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
764                 << "layout(location = 0) out vec4 outColor;\n"
765                 << "layout(location = 1) in vec2 fragTexCoord;\n";
766
767         fragmentSrc << "layout(binding = 0) uniform sampler2D compTexSampler;\n";
768
769         if (m_twoSamplers)
770         {
771                 fragmentSrc
772                         << "layout(binding = 1) uniform usampler2D texSampler;\n"
773                         << "layout(push_constant) uniform constants {\n"
774                         << "    int pass;\n"
775                         << "} pc;\n"
776                         << "void main() {\n"
777                         << "    if (pc.pass == 1)\n"
778                         << "        outColor = texture(compTexSampler, fragTexCoord);\n"
779                         << "    else"
780                         << "        outColor = texture(texSampler, fragTexCoord);\n";
781         }
782         else
783         {
784                 fragmentSrc
785                         << "void main() {\n"
786                         << "    outColor = texture(compTexSampler, fragTexCoord);\n";
787         }
788
789         fragmentSrc << "}\n";
790
791         programCollection.glslSources.add("comp") << glu::ComputeSource(computeSrc.str());
792         programCollection.glslSources.add("vert") << glu::VertexSource(vertexSrc.str());
793         programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSrc.str());
794 }
795
796 TestInstance* SampleDrawnTextureTest::createInstance (Context& context) const
797 {
798         return new SampleDrawnTextureTestInstance(context, m_imageFormat, m_imageViewFormat, m_twoSamplers, m_cubemap);
799 }
800
801 } // anonymous ns
802
803 tcu::TestCaseGroup* createImageSampleDrawnTextureTests  (tcu::TestContext& testCtx)
804 {
805         /* If both samplers are enabled, the test works as follows:
806          *
807          * Pass 0:
808          * - Compute shader fills a storage image with values that are pure blue compressed with
809          *   either the BC1 or BC3 algorithm.
810          * - Fragment shader samples the image and draws the values on a target image.
811          * - As the sampled values are accessed through an image view using an uncompressed
812          *   format, they remain compressed and the drawn image ends up being garbage.
813          * Pass 1:
814          * - Fragment shader samples the image. On this pass, the image view uses
815          *   a block-compressed format and correctly interprets the sampled values.
816          * - As the values are uncompressed now, the target image is filled
817          *   with pure blue and the test passes.
818
819          * Only one sampler enabled:
820          * Pass 0:
821          * - Compute shader fills a storage image with values that are pure red compressed
822          *   with either the BC1 or BC3 algorithm.
823          * - Fragment shader samples the image through an image view which interprets the values
824          *   correctly. The values are drawn on a target image. The test doesn't pass yet
825          *   since the image is red.
826          * Pass 1:
827          * - Compute shader fills the storage image with values that are pure blue compressed
828          *   with the same algorithm as on the previous pass.
829          * - Fragment shader samples the image through an image view which interprets the values
830          *   correctly. The values are drawn on the target image and the test passes.
831          *
832          * If cubemaps are enabled:
833          * Pass 0:
834          * - If both samplers are enabled, draw compressed pure blue on the faces. Otherwise pure red.
835          * - Sample the image through an image view with or without compressed format as in the cases
836          *   without cubemaps.
837          * Pass 1:
838          * - If only one sampler is enabled, redraw the faces with pure blue
839          * - Sample the image. Sampling should produce colors with a 0.0 red component and with > 0.0
840          *   blue and alpha components.
841          */
842
843         const bool twoSamplers  = true;
844         const bool cubemap              = true;
845
846         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "sample_texture", "Sample texture that has been rendered to tests"));
847
848         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format_cubemap", "", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, !twoSamplers, cubemap));
849         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format_cubemap", "", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, !twoSamplers, cubemap));
850         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format_two_samplers_cubemap", "", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, twoSamplers, cubemap));
851         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format_two_samplers_cubemap", "", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, twoSamplers, cubemap));
852
853         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format", "", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, !twoSamplers, false));
854         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "64_bit_compressed_format_two_samplers", "", VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_R32G32_UINT, twoSamplers, false));
855         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format", "", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, !twoSamplers, false));
856         testGroup->addChild(new SampleDrawnTextureTest(testCtx, "128_bit_compressed_format_two_samplers", "", VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_R32G32B32A32_UINT, twoSamplers, false));
857
858         return testGroup.release();
859 }
860
861 } // image
862 } // vkt