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