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