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 ¶meters);
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 ¶meters)
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, ©Region);
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, ©Region);
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 ¶meters);
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 ¶meters)
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