xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/image/vktImageAstcDecodeModeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file  vktImageAstcDecodeModeTests.cpp
21  * \brief Astc decode mode tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktImageAstcDecodeModeTests.hpp"
25 #include "vktImageLoadStoreUtil.hpp"
26 
27 #include "vktTestCaseUtil.hpp"
28 #include "vkBarrierUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 
35 #include "tcuAstcUtil.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuTexture.hpp"
38 #include "tcuCompressedTexture.hpp"
39 #include "tcuImageCompare.hpp"
40 
41 #include "deRandom.hpp"
42 #include <vector>
43 
44 using namespace vk;
45 namespace vkt
46 {
47 namespace image
48 {
49 namespace
50 {
51 using de::MovePtr;
52 using de::Random;
53 using de::SharedPtr;
54 using std::string;
55 using std::vector;
56 using tcu::CompressedTexFormat;
57 using tcu::CompressedTexture;
58 using tcu::IVec3;
59 using tcu::TestContext;
60 using tcu::TestStatus;
61 using tcu::UVec3;
62 
63 struct TestParameters
64 {
65     ImageType imageType;
66     UVec3 imageSize;
67 
68     VkFormat testedFormat;
69     bool testedIsUnorm;
70     VkFormat testedDecodeMode;
71     VkImageUsageFlags testedImageUsage;
72 
73     VkFormat resultFormat;
74     VkImageUsageFlags resultImageUsage;
75 };
76 
77 class BasicComputeTestInstance : public TestInstance
78 {
79 public:
80     BasicComputeTestInstance(Context &context, const TestParameters &parameters);
81 
82     TestStatus iterate(void);
83 
84 protected:
85     const TestParameters m_parameters;
86 };
87 
BasicComputeTestInstance(Context & context,const TestParameters & parameters)88 BasicComputeTestInstance::BasicComputeTestInstance(Context &context, const TestParameters &parameters)
89     : TestInstance(context)
90     , m_parameters(parameters)
91 {
92 }
93 
iterate(void)94 TestStatus BasicComputeTestInstance::iterate(void)
95 {
96     Allocator &allocator            = m_context.getDefaultAllocator();
97     const DeviceInterface &vk       = m_context.getDeviceInterface();
98     const VkDevice device           = m_context.getDevice();
99     const VkQueue queue             = m_context.getUniversalQueue();
100     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
101     const VkImageType imageType     = mapImageType(m_parameters.imageType);
102     const VkExtent3D extentCompressed =
103         makeExtent3D(getCompressedImageResolutionInBlocks(m_parameters.testedFormat, m_parameters.imageSize));
104     const VkExtent3D extentUnCompressed = makeExtent3D(m_parameters.imageSize);
105     const Unique<VkCommandPool> cmdPool(
106         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
107     const Unique<VkCommandBuffer> cmdBuffer(
108         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
109     const Unique<VkShaderModule> shaderModule(
110         createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
111 
112     const VkImageCreateInfo compressedImageInfo = {
113         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
114         DE_NULL,                             // const void* pNext;
115         VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
116             VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT,          // VkImageCreateFlags flags;
117         imageType,                                                    // VkImageType imageType;
118         m_parameters.testedFormat,                                    // VkFormat format;
119         extentCompressed,                                             // VkExtent3D extent;
120         1u,                                                           // uint32_t mipLevels;
121         1u,                                                           // uint32_t arrayLayers;
122         VK_SAMPLE_COUNT_1_BIT,                                        // VkSampleCountFlagBits samples;
123         VK_IMAGE_TILING_OPTIMAL,                                      // VkImageTiling tiling;
124         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
125         VK_SHARING_MODE_EXCLUSIVE,                                    // VkSharingMode sharingMode;
126         0u,                                                           // uint32_t queueFamilyIndexCount;
127         DE_NULL,                                                      // const uint32_t* pQueueFamilyIndices;
128         VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout initialLayout;
129     };
130 
131     const VkImageCreateInfo resultImageInfo = {
132         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
133         DE_NULL,                             // const void* pNext;
134         0u,                                  // VkImageCreateFlags flags;
135         imageType,                           // VkImageType imageType;
136         m_parameters.resultFormat,           // VkFormat format;
137         extentUnCompressed,                  // VkExtent3D extent;
138         1u,                                  // uint32_t mipLevels;
139         1u,                                  // uint32_t arrayLayers;
140         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
141         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
142         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
143             VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
144         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
145         0u,                                  // uint32_t queueFamilyIndexCount;
146         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
147         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
148     };
149 
150     // create images
151     Image testedImage(vk, device, allocator, compressedImageInfo, MemoryRequirement::Any);
152     Image referenceImage(vk, device, allocator, compressedImageInfo, MemoryRequirement::Any);
153     Image resultImage(vk, device, allocator, resultImageInfo, MemoryRequirement::Any);
154 
155     // create image views
156     const VkImageViewType imageViewType(mapImageViewType(m_parameters.imageType));
157     VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
158 
159     VkImageViewASTCDecodeModeEXT decodeMode = {VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT, DE_NULL,
160                                                m_parameters.testedDecodeMode};
161 
162     const VkImageViewCreateInfo imageViewParams = {
163         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
164         &decodeMode,                              // const void* pNext;
165         0u,                                       // VkImageViewCreateFlags flags;
166         testedImage.get(),                        // VkImage image;
167         imageViewType,                            // VkImageViewType viewType;
168         m_parameters.testedFormat,                // VkFormat format;
169         makeComponentMappingRGBA(),               // VkComponentMapping components;
170         subresourceRange,                         // VkImageSubresourceRange subresourceRange;
171     };
172 
173     Move<VkImageView> testedView = createImageView(vk, device, &imageViewParams);
174     Move<VkImageView> referenceView =
175         makeImageView(vk, device, referenceImage.get(), imageViewType, m_parameters.testedFormat, subresourceRange);
176     Move<VkImageView> resultView =
177         makeImageView(vk, device, resultImage.get(), imageViewType, m_parameters.resultFormat,
178                       makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, resultImageInfo.extent.depth, 0u,
179                                                 resultImageInfo.arrayLayers));
180 
181     Move<VkDescriptorSetLayout> descriptorSetLayout =
182         DescriptorSetLayoutBuilder()
183             .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT)
184             .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT)
185             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
186             .build(vk, device);
187     Move<VkDescriptorPool> descriptorPool =
188         DescriptorPoolBuilder()
189             .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, compressedImageInfo.arrayLayers)
190             .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, compressedImageInfo.arrayLayers)
191             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, resultImageInfo.arrayLayers)
192             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, resultImageInfo.arrayLayers);
193 
194     Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
195     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
196     const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
197 
198     const VkDeviceSize bufferSizeCompresed =
199         getCompressedImageSizeInBytes(m_parameters.testedFormat, m_parameters.imageSize);
200     const VkDeviceSize bufferSizeUncompressed = getImageSizeBytes(
201         IVec3((int)extentUnCompressed.width, (int)extentUnCompressed.height, (int)extentUnCompressed.depth),
202         m_parameters.resultFormat);
203     VkBufferCreateInfo compressedBufferCI = makeBufferCreateInfo(bufferSizeCompresed, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
204     VkBufferCreateInfo uncompressedBufferCI = makeBufferCreateInfo(
205         bufferSizeUncompressed, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
206     BufferWithMemory inBuffer(vk, device, allocator, compressedBufferCI, MemoryRequirement::HostVisible);
207     BufferWithMemory resultBuffer(vk, device, allocator, uncompressedBufferCI, MemoryRequirement::HostVisible);
208     Move<VkSampler> sampler;
209 
210     // generate data for compressed image and copy it to in buffer
211     {
212         vector<uint8_t> generatedData;
213         generatedData.resize(static_cast<size_t>(bufferSizeCompresed));
214 
215         auto blocks = getCompressedImageResolutionInBlocks(m_parameters.testedFormat, m_parameters.imageSize);
216         tcu::astc::generateRandomValidBlocks(generatedData.data(), blocks.x() * blocks.y() * blocks.z(),
217                                              mapVkCompressedFormat(m_parameters.testedFormat),
218                                              tcu::TexDecompressionParams::ASTCMODE_LDR, 1);
219 
220         const Allocation &alloc = inBuffer.getAllocation();
221         deMemcpy(alloc.getHostPtr(), generatedData.data(), generatedData.size());
222         flushAlloc(vk, device, alloc);
223     }
224 
225     {
226         const VkSamplerCreateInfo createInfo = {
227             VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   //VkStructureType sType;
228             DE_NULL,                                 //const void* pNext;
229             0u,                                      //VkSamplerCreateFlags flags;
230             VK_FILTER_NEAREST,                       //VkFilter magFilter;
231             VK_FILTER_NEAREST,                       //VkFilter minFilter;
232             VK_SAMPLER_MIPMAP_MODE_NEAREST,          //VkSamplerMipmapMode mipmapMode;
233             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   //VkSamplerAddressMode addressModeU;
234             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   //VkSamplerAddressMode addressModeV;
235             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   //VkSamplerAddressMode addressModeW;
236             0.0f,                                    //float mipLodBias;
237             VK_FALSE,                                //VkBool32 anisotropyEnable;
238             1.0f,                                    //float maxAnisotropy;
239             VK_FALSE,                                //VkBool32 compareEnable;
240             VK_COMPARE_OP_EQUAL,                     //VkCompareOp compareOp;
241             0.0f,                                    //float minLod;
242             1.0f,                                    //float maxLod;
243             VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, //VkBorderColor borderColor;
244             VK_FALSE,                                //VkBool32 unnormalizedCoordinates;
245         };
246         sampler = createSampler(vk, device, &createInfo);
247     }
248 
249     VkDescriptorImageInfo descriptorImageInfos[] = {
250         makeDescriptorImageInfo(*sampler, *testedView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
251         makeDescriptorImageInfo(*sampler, *referenceView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
252         makeDescriptorImageInfo(DE_NULL, *resultView, VK_IMAGE_LAYOUT_GENERAL),
253     };
254     DescriptorSetUpdateBuilder()
255         .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
256                      VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfos[0])
257         .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u),
258                      VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfos[1])
259         .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(2u),
260                      VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[2])
261         .update(vk, device);
262 
263     beginCommandBuffer(vk, *cmdBuffer);
264     {
265         // copy input buffer to tested and reference images
266         {
267             Image *inImages[] = {&testedImage, &referenceImage};
268             for (Image *image : inImages)
269             {
270                 const VkImageMemoryBarrier preCopyImageBarrier =
271                     makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
272                                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, image->get(), subresourceRange);
273 
274                 const VkBufferMemoryBarrier flushHostCopyBarrier = makeBufferMemoryBarrier(
275                     VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, inBuffer.get(), 0ull, bufferSizeCompresed);
276 
277                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
278                                       (VkDependencyFlags)0, 0u, (const VkMemoryBarrier *)DE_NULL, 1u,
279                                       &flushHostCopyBarrier, 1u, &preCopyImageBarrier);
280 
281                 const VkBufferImageCopy copyRegion = {
282                     0ull, //VkDeviceSize bufferOffset;
283                     0u,   //uint32_t bufferRowLength;
284                     0u,   //uint32_t bufferImageHeight;
285                     makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
286                                                1u), //VkImageSubresourceLayers imageSubresource;
287                     makeOffset3D(0, 0, 0),          //VkOffset3D imageOffset;
288                     extentCompressed,               //VkExtent3D imageExtent;
289                 };
290 
291                 vk.cmdCopyBufferToImage(*cmdBuffer, inBuffer.get(), image->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
292                                         1u, &copyRegion);
293             }
294         }
295 
296         // bind pipeline and descriptors
297         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
298         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u,
299                                  &descriptorSet.get(), 0u, DE_NULL);
300 
301         {
302             const VkImageMemoryBarrier preShaderImageBarriers[] = {
303                 makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
304                                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
305                                        testedImage.get(), subresourceRange),
306 
307                 makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
308                                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
309                                        referenceImage.get(), subresourceRange),
310 
311                 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
312                                        VK_IMAGE_LAYOUT_GENERAL, resultImage.get(), subresourceRange)};
313 
314             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
315                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0u,
316                                   (const VkBufferMemoryBarrier *)DE_NULL, DE_LENGTH_OF_ARRAY(preShaderImageBarriers),
317                                   preShaderImageBarriers);
318         }
319 
320         vk.cmdDispatch(*cmdBuffer, extentUnCompressed.width, extentUnCompressed.height, extentUnCompressed.depth);
321 
322         {
323             const VkImageMemoryBarrier postShaderImageBarriers[] = {
324                 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
325                                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resultImage.get(), subresourceRange)};
326 
327             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
328                                   (VkDependencyFlags)0, 0u, (const VkMemoryBarrier *)DE_NULL, 0u,
329                                   (const VkBufferMemoryBarrier *)DE_NULL, DE_LENGTH_OF_ARRAY(postShaderImageBarriers),
330                                   postShaderImageBarriers);
331         }
332 
333         const VkBufferImageCopy copyRegion = {
334             0ull, // VkDeviceSize bufferOffset;
335             0u,   // uint32_t bufferRowLength;
336             0u,   // uint32_t bufferImageHeight;
337             makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
338                                        1u), // VkImageSubresourceLayers imageSubresource;
339             makeOffset3D(0, 0, 0),          // VkOffset3D imageOffset;
340             resultImageInfo.extent,         // VkExtent3D imageExtent;
341         };
342         vk.cmdCopyImageToBuffer(*cmdBuffer, resultImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resultBuffer.get(),
343                                 1u, &copyRegion);
344 
345         {
346             const VkBufferMemoryBarrier postCopyBufferBarrier[] = {
347                 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, resultBuffer.get(), 0ull,
348                                         bufferSizeUncompressed),
349             };
350 
351             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
352                                   (VkDependencyFlags)0, 0u, (const VkMemoryBarrier *)DE_NULL,
353                                   DE_LENGTH_OF_ARRAY(postCopyBufferBarrier), postCopyBufferBarrier, 0u,
354                                   (const VkImageMemoryBarrier *)DE_NULL);
355         }
356     }
357     endCommandBuffer(vk, *cmdBuffer);
358     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
359 
360     const Allocation &resultAlloc = resultBuffer.getAllocation();
361     invalidateAlloc(vk, device, resultAlloc);
362 
363     // verification is done in shader - here we just check if one of pixels has wrong value
364     const size_t numBytes = static_cast<size_t>(bufferSizeUncompressed);
365     uint8_t *result       = static_cast<uint8_t *>(resultAlloc.getHostPtr());
366     for (size_t i = 0; i < numBytes; i += 4)
367     {
368         // expected result should be around 128 (if reference is same as tested mode then we return 0.5)
369         if ((result[i] < 100) || (result[i] > 150))
370             return TestStatus::fail("Fail");
371     }
372 
373     return TestStatus::pass("Pass");
374 }
375 
376 class AstcDecodeModeCase : public TestCase
377 {
378 public:
379     AstcDecodeModeCase(TestContext &testCtx, const std::string &name, const TestParameters &parameters);
380     virtual void checkSupport(Context &context) const;
381     void initPrograms(SourceCollections &programCollection) const;
382     TestInstance *createInstance(Context &context) const;
383 
384 protected:
385     const TestParameters m_parameters;
386 };
387 
AstcDecodeModeCase(TestContext & testCtx,const std::string & name,const TestParameters & parameters)388 AstcDecodeModeCase::AstcDecodeModeCase(TestContext &testCtx, const std::string &name, const TestParameters &parameters)
389     : TestCase(testCtx, name)
390     , m_parameters(parameters)
391 {
392 }
393 
checkSupport(Context & context) const394 void AstcDecodeModeCase::checkSupport(Context &context) const
395 {
396     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
397     const InstanceInterface &vk           = context.getInstanceInterface();
398 
399     context.requireDeviceFunctionality("VK_EXT_astc_decode_mode");
400     if (!getPhysicalDeviceFeatures(vk, physicalDevice).textureCompressionASTC_LDR)
401         TCU_THROW(NotSupportedError, "textureCompressionASTC_LDR not supported");
402 
403     VkImageFormatProperties imageFormatProperties;
404     if (VK_ERROR_FORMAT_NOT_SUPPORTED ==
405         vk.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.testedFormat,
406                                                   mapImageType(m_parameters.imageType), VK_IMAGE_TILING_OPTIMAL,
407                                                   m_parameters.testedImageUsage, 0u, &imageFormatProperties))
408         TCU_THROW(NotSupportedError, "Operation not supported with this image format");
409 
410     if (VK_ERROR_FORMAT_NOT_SUPPORTED ==
411         vk.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.resultFormat,
412                                                   mapImageType(m_parameters.imageType), VK_IMAGE_TILING_OPTIMAL,
413                                                   m_parameters.resultImageUsage, 0u, &imageFormatProperties))
414         TCU_THROW(NotSupportedError, "Operation not supported with this image format");
415 
416     if ((m_parameters.testedDecodeMode == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) &&
417         !context.getASTCDecodeFeaturesEXT().decodeModeSharedExponent)
418         TCU_THROW(NotSupportedError, "decodeModeSharedExponent not supported");
419 
420     VkFormatProperties properties;
421     context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(),
422                                                                      m_parameters.resultFormat, &properties);
423     if (!(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
424         TCU_THROW(NotSupportedError, "Format storage feature not supported");
425 }
426 
initPrograms(vk::SourceCollections & programCollection) const427 void AstcDecodeModeCase::initPrograms(vk::SourceCollections &programCollection) const
428 {
429     DE_ASSERT(m_parameters.imageSize.x() > 0);
430     DE_ASSERT(m_parameters.imageSize.y() > 0);
431 
432     const string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_parameters.resultFormat));
433     const string imageTypeStr = getShaderImageType(mapVkFormat(m_parameters.resultFormat), m_parameters.imageType);
434 
435     std::ostringstream src;
436     src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
437         << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n\n"
438         << "layout (binding = 0) uniform sampler2D compressed_tested;\n"
439         << "layout (binding = 1) uniform sampler2D compressed_reference;\n"
440         << "layout (binding = 2, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " result;\n"
441         << "void main (void)\n"
442         << "{\n"
443         << "    const vec2 pixels_resolution = vec2(gl_NumWorkGroups.xy);\n"
444         << "    const vec2 cord = vec2(gl_GlobalInvocationID.xy) / vec2(pixels_resolution);\n"
445         << "    const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); \n"
446         << "    vec4 tested = texture(compressed_tested, cord);\n"
447         << "    vec4 reference = texture(compressed_reference, cord);\n";
448 
449     // special case for e5b9g9r9 decode mode that was set on unorm astc formats
450     // here negative values are clamped to zero and alpha is set to 1
451     if (m_parameters.testedIsUnorm && (m_parameters.testedDecodeMode == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32))
452         src << "    reference = max(vec4(0,0,0,1), reference);\n"
453                "    float result_color = 0.5 * float(distance(tested, reference) < 0.01);\n";
454     else
455         src << "    float result_color = 0.5 * float(distance(tested, reference) < 0.01);\n";
456 
457     src << "    imageStore(result, pos, vec4(result_color));\n"
458         << "}\n";
459 
460     programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
461 }
462 
createInstance(Context & context) const463 TestInstance *AstcDecodeModeCase::createInstance(Context &context) const
464 {
465     return new BasicComputeTestInstance(context, m_parameters);
466 }
467 
468 } // namespace
469 
createImageAstcDecodeModeTests(tcu::TestContext & testCtx)470 tcu::TestCaseGroup *createImageAstcDecodeModeTests(tcu::TestContext &testCtx)
471 {
472     struct FormatData
473     {
474         VkFormat format;
475         std::string name;
476         bool isUnorm;
477     };
478     const FormatData astcFormats[] = {
479         {VK_FORMAT_ASTC_4x4_UNORM_BLOCK, "4x4_unorm", true},     {VK_FORMAT_ASTC_4x4_SRGB_BLOCK, "4x4_srgb", false},
480         {VK_FORMAT_ASTC_5x4_UNORM_BLOCK, "5x4_unorm", true},     {VK_FORMAT_ASTC_5x4_SRGB_BLOCK, "5x4_srgb", false},
481         {VK_FORMAT_ASTC_5x5_UNORM_BLOCK, "5x5_unorm", true},     {VK_FORMAT_ASTC_5x5_SRGB_BLOCK, "5x5_srgb", false},
482         {VK_FORMAT_ASTC_6x5_UNORM_BLOCK, "6x5_unorm", true},     {VK_FORMAT_ASTC_6x5_SRGB_BLOCK, "6x5_srgb", false},
483         {VK_FORMAT_ASTC_6x6_UNORM_BLOCK, "6x6_unorm", true},     {VK_FORMAT_ASTC_6x6_SRGB_BLOCK, "6x6_srgb", false},
484         {VK_FORMAT_ASTC_8x5_UNORM_BLOCK, "8x5_unorm", true},     {VK_FORMAT_ASTC_8x5_SRGB_BLOCK, "8x5_srgb", false},
485         {VK_FORMAT_ASTC_8x6_UNORM_BLOCK, "8x6_unorm", true},     {VK_FORMAT_ASTC_8x6_SRGB_BLOCK, "8x6_srgb", false},
486         {VK_FORMAT_ASTC_8x8_UNORM_BLOCK, "8x8_unorm", true},     {VK_FORMAT_ASTC_8x8_SRGB_BLOCK, "8x8_srgb", false},
487         {VK_FORMAT_ASTC_10x5_UNORM_BLOCK, "10x5_unorm", true},   {VK_FORMAT_ASTC_10x5_SRGB_BLOCK, "10x5_srgb", false},
488         {VK_FORMAT_ASTC_10x6_UNORM_BLOCK, "10x6_unorm", true},   {VK_FORMAT_ASTC_10x6_SRGB_BLOCK, "10x6_srgb", false},
489         {VK_FORMAT_ASTC_10x8_UNORM_BLOCK, "10x8_unorm", true},   {VK_FORMAT_ASTC_10x8_SRGB_BLOCK, "10x8_srgb", false},
490         {VK_FORMAT_ASTC_10x10_UNORM_BLOCK, "10x10_unorm", true}, {VK_FORMAT_ASTC_10x10_SRGB_BLOCK, "10x10_srgb", false},
491         {VK_FORMAT_ASTC_12x10_UNORM_BLOCK, "12x10_unorm", true}, {VK_FORMAT_ASTC_12x10_SRGB_BLOCK, "12x10_srgb", false},
492         {VK_FORMAT_ASTC_12x12_UNORM_BLOCK, "12x12_unorm", true}, {VK_FORMAT_ASTC_12x12_SRGB_BLOCK, "12x12_srgb", false},
493     };
494 
495     struct DecodeModeData
496     {
497         VkFormat mode;
498         std::string name;
499     };
500     const DecodeModeData decodeModes[] = {{VK_FORMAT_R16G16B16A16_SFLOAT, "r16g16b16a16_sfloat"},
501                                           {VK_FORMAT_R8G8B8A8_UNORM, "r8g8b8a8_unorm"},
502                                           {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, "e5b9g9r9_ufloat_pack32"}};
503 
504     // Intermediate decoding precision cases
505     MovePtr<tcu::TestCaseGroup> astcDecodeModeTests(new tcu::TestCaseGroup(testCtx, "astc_decode_mode"));
506     for (const FormatData &format : astcFormats)
507     {
508         for (const DecodeModeData &mode : decodeModes)
509         {
510             const TestParameters parameters = {IMAGE_TYPE_2D,
511                                                UVec3(64u, 64u, 1u),
512                                                format.format,
513                                                format.isUnorm,
514                                                mode.mode,
515                                                VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
516                                                    VK_IMAGE_USAGE_SAMPLED_BIT,
517                                                VK_FORMAT_R8G8B8A8_UNORM,
518                                                VK_IMAGE_USAGE_STORAGE_BIT};
519 
520             std::string name = format.name + "_to_" + mode.name;
521             astcDecodeModeTests->addChild(new AstcDecodeModeCase(testCtx, name, parameters));
522         }
523     }
524 
525     return astcDecodeModeTests.release();
526 }
527 
528 } // namespace image
529 } // namespace vkt
530