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