• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 Google Inc.
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 Texture conversion tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktTextureConversionTests.hpp"
26 #include "vktAmberTestCase.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktTextureTestUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "tcuTexture.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 #include "deSharedPtr.hpp"
34 
35 #include <cmath>
36 #include <memory>
37 
38 namespace vkt
39 {
40 namespace texture
41 {
42 
43 using namespace vk;
44 
45 namespace
46 {
47 
48 using namespace texture::util;
49 using namespace glu::TextureTestUtil;
50 
51 class SnormLinearClampInstance : public TestInstance
52 {
53 public:
54 	struct Params
55 	{
56 		VkFormat	format;
57 		int			width;
58 		int			height;
59 	};
60 							SnormLinearClampInstance	(vkt::Context&					context,
61 														 de::SharedPtr<Params>			params);
62 
63 	virtual tcu::TestStatus	iterate						(void) override;
64 
65 protected:
66 	tcu::IVec4				computeColorDistance		() const;
67 	bool					verifyPixels				(const tcu::PixelBufferAccess&	rendered,
68 														 const tcu::PixelBufferAccess&	reference,
69 														 const ReferenceParams&			samplerParams,
70 														 const std::vector<float>&		texCoords)		const;
71 
72 	static int				lim							(const tcu::TextureFormat&		format,
73 														 int							channelIdx);
74 
75 private:
76 	const de::SharedPtr<Params>	m_params;
77 	const tcu::TextureFormat	m_inFormat;
78 	const VkFormat				m_outFormat;
79 	TestTexture2DSp				m_hwTexture;
80 	tcu::Texture2D				m_swTexture;
81 	TextureRenderer				m_renderer;
82 
83 	const tcu::IVec4			m_cd;
84 	const tcu::IVec4			m_a;
85 	const tcu::IVec4			m_b;
86 	const tcu::IVec4			m_c;
87 	const tcu::IVec4			m_d;
88 
89 public:
90 	static const int			textureWidth	= 7;
91 	static const int			textureHeight	= 7;
92 };
93 
SnormLinearClampInstance(vkt::Context & context,de::SharedPtr<Params> params)94 SnormLinearClampInstance::SnormLinearClampInstance (vkt::Context& context, de::SharedPtr<Params> params)
95 	: TestInstance	(context)
96 	, m_params		(params)
97 	, m_inFormat	(mapVkFormat(m_params->format))
98 	, m_outFormat	(VK_FORMAT_R32G32B32A32_SFLOAT)
99 	, m_hwTexture	(TestTexture2DSp(new pipeline::TestTexture2D(m_inFormat, textureWidth, textureHeight)))
100 	, m_swTexture	(m_inFormat, textureWidth, textureHeight, 1)
101 	, m_renderer	(context, VK_SAMPLE_COUNT_1_BIT, m_params->width, m_params->height, 1u, makeComponentMappingRGBA(), VK_IMAGE_TYPE_2D, VK_IMAGE_VIEW_TYPE_2D, m_outFormat)
102 	, m_cd			(computeColorDistance())
103 	, m_a			(lim(m_inFormat, 0),			lim(m_inFormat, 1)+m_cd[1]*2,	lim(m_inFormat, 2),				lim(m_inFormat, 3)+m_cd[3]*2)
104 	, m_b			(lim(m_inFormat, 0)+m_cd[0]*2,	lim(m_inFormat, 1),				lim(m_inFormat, 2)+m_cd[2]*2,	lim(m_inFormat, 3)			)
105 	, m_c			(lim(m_inFormat, 0)+m_cd[0]*1,	lim(m_inFormat, 1)+m_cd[1]*1,	lim(m_inFormat, 2)+m_cd[2]*1,	lim(m_inFormat, 3)+m_cd[3]*1)
106 	, m_d			(lim(m_inFormat, 0),			lim(m_inFormat, 1),				lim(m_inFormat, 2),				lim(m_inFormat, 3)			)
107 {
108 	tcu::IVec4 data[textureWidth * textureHeight] =
109 	{
110 		m_a, m_b, m_c, m_d, m_c, m_b, m_a,
111 		m_b, m_a, m_c, m_d, m_c, m_a, m_b,
112 		m_c, m_c, m_c, m_d, m_c, m_c, m_c,
113 		m_d, m_d, m_d, m_c, m_d, m_d, m_d,
114 		m_c, m_c, m_c, m_d, m_c, m_c, m_c,
115 		m_b, m_a, m_c, m_d, m_c, m_a, m_b,
116 		m_a, m_b, m_c, m_d, m_c, m_b, m_a,
117 	};
118 
119 	m_swTexture.allocLevel(0);
120 
121 	const tcu::PixelBufferAccess& swAccess	= m_swTexture.getLevel(0);
122 	const tcu::PixelBufferAccess& hwAccess	= m_hwTexture->getLevel(0, 0);
123 
124 	for (int y = 0; y < textureHeight; ++y)
125 	{
126 		for (int x = 0; x < textureWidth; ++x)
127 		{
128 			swAccess.setPixel(data[y*textureWidth+x], x, y);
129 			hwAccess.setPixel(data[y*textureWidth+x], x, y);
130 		}
131 	}
132 
133 	m_renderer.add2DTexture(m_hwTexture, VK_IMAGE_ASPECT_COLOR_BIT, TextureBinding::ImageBackingMode::IMAGE_BACKING_MODE_REGULAR);
134 }
135 
lim(const tcu::TextureFormat & format,int channelIdx)136 int SnormLinearClampInstance::lim (const tcu::TextureFormat& format, int channelIdx)
137 {
138 	auto   channelBits(getTextureFormatBitDepth(format));
139 	return channelBits[channelIdx] ? (-deIntMaxValue32(channelBits[channelIdx])) : (-1);
140 }
141 
computeColorDistance() const142 tcu::IVec4 SnormLinearClampInstance::computeColorDistance () const
143 {
144 	return tcu::IVec4
145 	(
146 		static_cast<int>(std::floor(static_cast<float>(-lim(m_inFormat, 0)) / 127.0f)),
147 		static_cast<int>(std::floor(static_cast<float>(-lim(m_inFormat, 0)) / 127.0f)),
148 		static_cast<int>(std::floor(static_cast<float>(-lim(m_inFormat, 0)) / 127.0f)),
149 		static_cast<int>(std::floor(static_cast<float>(-lim(m_inFormat, 0)) / 127.0f))
150 	);
151 }
152 
verifyPixels(const tcu::PixelBufferAccess & rendered,const tcu::PixelBufferAccess & reference,const ReferenceParams & samplerParams,const std::vector<float> & texCoords) const153 bool SnormLinearClampInstance::verifyPixels	(const tcu::PixelBufferAccess& rendered, const tcu::PixelBufferAccess& reference, const ReferenceParams& samplerParams, const std::vector<float>& texCoords) const
154 {
155 	tcu::LodPrecision				lodPrec;
156 	tcu::LookupPrecision			lookupPrec;
157 
158 	const int						nuc				(getNumUsedChannels(m_inFormat.order));
159 	const int						width			(m_renderer.getRenderWidth());
160 	const int						height			(m_renderer.getRenderHeight());
161 
162 	const tcu::IVec4				colorDistance	(computeColorDistance());
163 	std::unique_ptr<deUint8[]>		errorMaskData	(new deUint8[width * height * 4 * 4]);
164 	tcu::PixelBufferAccess			errorMask		(mapVkFormat(m_outFormat), width, height, 1, errorMaskData.get());
165 
166 
167 	lodPrec.derivateBits			= 18;
168 	lodPrec.lodBits					= 5;
169 
170 	lookupPrec.uvwBits				= tcu::IVec3(5,5,0);
171 	lookupPrec.coordBits			= tcu::IVec3(20,20,0);
172 	lookupPrec.colorMask			= tcu::BVec4(nuc >= 1, nuc >= 2, nuc >=3, nuc >= 4);
173 	lookupPrec.colorThreshold		= tcu::Vec4(0.9f/float(colorDistance[0]),
174 												0.9f/float(colorDistance[1]),
175 												0.9f/float(colorDistance[2]),
176 												0.9f/float(colorDistance[3]));
177 
178 	const int numFailedPixels		= glu::TextureTestUtil::computeTextureLookupDiff(rendered, reference, errorMask,
179 																					 m_swTexture, texCoords.data(), samplerParams,
180 																					 lookupPrec, lodPrec, /*watchDog*/nullptr);
181 	if (numFailedPixels)
182 	{
183 		const int	numTotalPixels	= width * height;
184 		auto&		log				= m_context.getTestContext().getLog();
185 		const auto	formatName		= de::toLower(std::string(getFormatName(m_params->format)).substr(10));
186 
187 		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
188 		log << tcu::TestLog::Message << "       " << float(numFailedPixels * 100)/float(numTotalPixels) << "% failed from " << numTotalPixels << " compared pixel count." << tcu::TestLog::EndMessage;
189 		log << tcu::TestLog::Message << "       ColorThreshold: " << lookupPrec.colorThreshold << ", ColorMask: " << lookupPrec.colorMask << tcu::TestLog::EndMessage;
190 
191 		log << tcu::TestLog::ImageSet("VerifyResult", "Verification result");
192 		{
193 			log << tcu::TestLog::Image("Res_"+formatName, "Rendered image", rendered);
194 			log << tcu::TestLog::Image("Ref_"+formatName, "Reference image", reference);
195 			log << tcu::TestLog::Image("Err_"+formatName, "Error mask image", errorMask);
196 		}
197 		log << tcu::TestLog::EndImageSet;
198 	}
199 
200 	int numOutOfRangePixels			= 0;
201 	for (int y = 0; y < height; ++y)
202 	{
203 		for (int x = 0; x < width; ++x)
204 		{
205 			const auto px = rendered.getPixel(x, y);
206 			if (tcu::boolAny(tcu::lessThan(px, tcu::Vec4(-1.0f))) || tcu::boolAny(tcu::greaterThan(px, tcu::Vec4(+1.0f))))
207 				++numOutOfRangePixels;
208 		}
209 	}
210 
211 	if (numOutOfRangePixels)
212 	{
213 		auto&		log					= m_context.getTestContext().getLog();
214 		log << tcu::TestLog::Message << "ERROR: Found " << numOutOfRangePixels << " out of range [-1.0f, +1.0f]." << tcu::TestLog::EndMessage;
215 	}
216 
217 	return (numFailedPixels == 0 && numOutOfRangePixels == 0);
218 }
219 
iterate(void)220 tcu::TestStatus SnormLinearClampInstance::iterate (void)
221 {
222 	std::vector<float>				texCoords		(8);
223 	ReferenceParams					samplerParams	(TEXTURETYPE_2D);
224 	tcu::TextureFormat				resultFormat	(mapVkFormat(m_outFormat));
225 
226 	// Setup renderers.
227 	const int						width			(m_renderer.getRenderWidth());
228 	const int						height			(m_renderer.getRenderHeight());
229 	std::unique_ptr<deUint8[]>		renderedData	(new deUint8[width * height * 4 * 4]);
230 	std::unique_ptr<deUint8[]>		referenceData	(new deUint8[width * height * 4 * 4]);
231 	tcu::PixelBufferAccess			rendered		(resultFormat, width, height, 1, renderedData.get());
232 	tcu::PixelBufferAccess			reference		(resultFormat, width, height, 1, referenceData.get());
233 
234 	// Setup sampler params.
235 	samplerParams.sampler			= util::createSampler(tcu::Sampler::WrapMode::REPEAT_GL, tcu::Sampler::WrapMode::REPEAT_GL,
236 														  tcu::Sampler::FilterMode::LINEAR, tcu::Sampler::FilterMode::LINEAR, true);
237 	samplerParams.samplerType		= SAMPLERTYPE_FLOAT;
238 	samplerParams.lodMode			= LODMODE_EXACT;
239 	samplerParams.colorScale		= tcu::Vec4(1.0f);
240 	samplerParams.colorBias			= tcu::Vec4(0.0f);
241 
242 	// Compute texture coordinates.
243 	computeQuadTexCoord2D(texCoords, tcu::Vec2(0.0f), tcu::Vec2(1.0f));
244 
245 	// Peform online rendering with Vulkan.
246 	m_renderer.renderQuad(rendered, 0, texCoords.data(), samplerParams);
247 
248 	// Perform offline rendering with software renderer.
249 	sampleTexture(reference, m_swTexture, texCoords.data(), samplerParams);
250 
251 	return verifyPixels(rendered, reference, samplerParams, texCoords)
252 			? tcu::TestStatus::pass("")
253 			: tcu::TestStatus::fail("Pixels verification failed");
254 }
255 
256 class SnormLinearClampTestCase : public TestCase
257 {
258 public:
259 	using ParamsSp = de::SharedPtr<SnormLinearClampInstance::Params>;
260 
SnormLinearClampTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,ParamsSp params)261 						SnormLinearClampTestCase	(tcu::TestContext&	testCtx,
262 													 const std::string&	name,
263 													 const std::string&	description,
264 													 ParamsSp			params)
265 		: TestCase	(testCtx, name, description)
266 		, m_params	(params)
267 	{
268 	}
269 
createInstance(vkt::Context & context) const270 	vkt::TestInstance*	createInstance				(vkt::Context&		context) const override
271 	{
272 		return new SnormLinearClampInstance(context, m_params);
273 	}
274 
checkSupport(vkt::Context & context) const275 	virtual void		checkSupport				(vkt::Context&		context) const override
276 	{
277 		VkFormatProperties		formatProperties;
278 
279 		context.getInstanceInterface().getPhysicalDeviceFormatProperties(
280 				context.getPhysicalDevice(),
281 				m_params->format,
282 				&formatProperties);
283 
284 		if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
285 			TCU_THROW(NotSupportedError, "Linear filtering for this image format is not supported");
286 	}
287 
initPrograms(SourceCollections & programCollection) const288 	virtual void		initPrograms				(SourceCollections&	programCollection) const override
289 	{
290 		initializePrograms(programCollection, glu::Precision::PRECISION_HIGHP, std::vector<Program>({PROGRAM_2D_FLOAT}), DE_NULL, glu::Precision::PRECISION_HIGHP);
291 	}
292 
293 private:
294 	ParamsSp	m_params;
295 };
296 
populateUfloatNegativeValuesTests(tcu::TestCaseGroup * group)297 void populateUfloatNegativeValuesTests (tcu::TestCaseGroup* group)
298 {
299 #ifndef CTS_USES_VULKANSC
300 	tcu::TestContext&	testCtx = group->getTestContext();
301 	VkImageUsageFlags	usage	= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
302 
303 	VkImageCreateInfo	info	=
304 	{
305 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType          sType
306 		DE_NULL,								// const void*              pNext
307 		0,										// VkImageCreateFlags       flags
308 		VK_IMAGE_TYPE_2D,						// VkImageType              imageType
309 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,		// VkFormat                 format
310 		{50u, 50u, 1u},							// VkExtent3D               extent
311 		1u,										// uint32_t                 mipLevels
312 		1u,										// uint32_t                 arrayLayers
313 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits    samples
314 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling            tiling
315 		usage,									// VkImageUsageFlags        usage
316 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode            sharingMode
317 		0u,										// uint32_t                 queueFamilyIndexCount
318 		DE_NULL,								// const uint32_t*          pQueueFamilyIndices
319 		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout            initialLayout
320 	};
321 
322 	group->addChild(cts_amber::createAmberTestCase(testCtx, "b10g11r11", "", "texture/conversion/ufloat_negative_values", "b10g11r11-ufloat-pack32.amber",
323 					std::vector<std::string>(), std::vector<VkImageCreateInfo>(1, info)));
324 #else
325 	DE_UNREF(group);
326 #endif
327 }
328 
populateSnormClampTests(tcu::TestCaseGroup * group)329 void populateSnormClampTests (tcu::TestCaseGroup* group)
330 {
331 #ifndef CTS_USES_VULKANSC
332 	tcu::TestContext&	testCtx	= group->getTestContext();
333 	VkImageUsageFlags	usage	= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
334 
335 	VkImageCreateInfo	info	=
336 	{
337 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType          sType
338 		DE_NULL,								// const void*              pNext
339 		0,										// VkImageCreateFlags       flags
340 		VK_IMAGE_TYPE_1D,						// VkImageType              imageType
341 		VK_FORMAT_UNDEFINED,					// VkFormat                 format
342 		{1u, 1u, 1u},							// VkExtent3D               extent
343 		1u,										// uint32_t                 mipLevels
344 		1u,										// uint32_t                 arrayLayers
345 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits    samples
346 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling            tiling
347 		usage,									// VkImageUsageFlags        usage
348 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode            sharingMode
349 		0u,										// uint32_t                 queueFamilyIndexCount
350 		DE_NULL,								// const uint32_t*          pQueueFamilyIndices
351 		VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout            initialLayout
352 	};
353 
354 	struct TestParams
355 	{
356 		std::string testName;
357 		std::string amberFile;
358 		VkFormat	format;
359 	} params[] =
360 	{
361 		{ "a2b10g10r10_snorm_pack32",	"a2b10g10r10-snorm-pack32.amber",	VK_FORMAT_A2B10G10R10_SNORM_PACK32	},
362 		{ "a2r10g10b10_snorm_pack32",	"a2r10g10b10-snorm-pack32.amber",	VK_FORMAT_A2R10G10B10_SNORM_PACK32	},
363 		{ "a8b8g8r8_snorm_pack32",		"a8b8g8r8-snorm-pack32.amber",		VK_FORMAT_A8B8G8R8_SNORM_PACK32		},
364 		{ "b8g8r8a8_snorm",				"b8g8r8a8-snorm.amber",				VK_FORMAT_B8G8R8A8_SNORM			},
365 		{ "b8g8r8_snorm",				"b8g8r8-snorm.amber",				VK_FORMAT_B8G8R8_SNORM				},
366 		{ "r16g16b16a16_snorm",			"r16g16b16a16-snorm.amber",			VK_FORMAT_R16G16B16A16_SNORM		},
367 		{ "r16g16b16_snorm",			"r16g16b16-snorm.amber",			VK_FORMAT_R16G16B16_SNORM			},
368 		{ "r16g16_snorm",				"r16g16-snorm.amber",				VK_FORMAT_R16G16_SNORM				},
369 		{ "r16_snorm",					"r16-snorm.amber",					VK_FORMAT_R16_SNORM					},
370 		{ "r8g8b8a8_snorm",				"r8g8b8a8-snorm.amber",				VK_FORMAT_R8G8B8A8_SNORM			},
371 		{ "r8g8b8_snorm",				"r8g8b8-snorm.amber",				VK_FORMAT_R8G8B8_SNORM				},
372 		{ "r8g8_snorm",					"r8g8-snorm.amber",					VK_FORMAT_R8G8_SNORM				},
373 		{ "r8_snorm",					"r8-snorm.amber",					VK_FORMAT_R8_SNORM					},
374 	};
375 
376 	for (const auto& param : params)
377 	{
378 		info.format = param.format;
379 		group->addChild(cts_amber::createAmberTestCase(testCtx, param.testName.c_str(), "", "texture/conversion/snorm_clamp", param.amberFile.c_str(),
380 						std::vector<std::string>(), std::vector<VkImageCreateInfo>(1, info)));
381 	}
382 #else
383 	DE_UNREF(group);
384 #endif
385 }
386 
populateSnormLinearClampTests(tcu::TestCaseGroup * group)387 void populateSnormLinearClampTests (tcu::TestCaseGroup* group)
388 {
389 	struct TestParams
390 	{
391 		std::string testName;
392 		VkFormat	format;
393 	}
394 	testParams[] =
395 	{
396 		{ "a2b10g10r10_snorm_pack32",	VK_FORMAT_A2B10G10R10_SNORM_PACK32	},
397 		{ "a2r10g10b10_snorm_pack32",	VK_FORMAT_A2R10G10B10_SNORM_PACK32	},
398 		{ "a8b8g8r8_snorm_pack32",		VK_FORMAT_A8B8G8R8_SNORM_PACK32		},
399 		{ "b8g8r8a8_snorm",				VK_FORMAT_B8G8R8A8_SNORM			},
400 		{ "b8g8r8_snorm",				VK_FORMAT_B8G8R8_SNORM				},
401 		{ "r16g16b16a16_snorm",			VK_FORMAT_R16G16B16A16_SNORM		},
402 		{ "r16g16b16_snorm",			VK_FORMAT_R16G16B16_SNORM			},
403 		{ "r16g16_snorm",				VK_FORMAT_R16G16_SNORM				},
404 		{ "r16_snorm",					VK_FORMAT_R16_SNORM					},
405 		{ "r8g8b8a8_snorm",				VK_FORMAT_R8G8B8A8_SNORM			},
406 		{ "r8g8b8_snorm",				VK_FORMAT_R8G8B8_SNORM				},
407 		{ "r8g8_snorm",					VK_FORMAT_R8G8_SNORM				},
408 		{ "r8_snorm",					VK_FORMAT_R8_SNORM					},
409 	};
410 
411 	tcu::TestContext&	testCtx				= group->getTestContext();
412 	int					sizeMultipler		= 20;
413 
414 	for (const auto& testParam : testParams)
415 	{
416 		const int		tw					= SnormLinearClampInstance::textureWidth * sizeMultipler;
417 		const int		th					= SnormLinearClampInstance::textureHeight * sizeMultipler;
418 
419 		de::SharedPtr<SnormLinearClampInstance::Params> params(new SnormLinearClampInstance::Params{testParam.format, tw, th});
420 		group->addChild(new SnormLinearClampTestCase(testCtx, testParam.testName, {}, params));
421 
422 		sizeMultipler += 2;
423 	}
424 }
425 
populateTextureConversionTests(tcu::TestCaseGroup * group)426 void populateTextureConversionTests (tcu::TestCaseGroup* group)
427 {
428 	tcu::TestContext& testCtx = group->getTestContext();
429 
430 	group->addChild(createTestGroup(testCtx, "ufloat_negative_values", "Tests for converting negative floats to unsigned floats", populateUfloatNegativeValuesTests));
431 	group->addChild(createTestGroup(testCtx, "snorm_clamp", "Tests for SNORM corner cases when smallest negative number gets clamped to -1", populateSnormClampTests));
432 	group->addChild(createTestGroup(testCtx, "snorm_clamp_linear", "Tests for SNORM corner cases when negative number gets clamped to -1 after applying linear filtering", populateSnormLinearClampTests));
433 }
434 
435 } // anonymous namespace
436 
createTextureConversionTests(tcu::TestContext & testCtx)437 tcu::TestCaseGroup* createTextureConversionTests (tcu::TestContext& testCtx)
438 {
439 	return createTestGroup(testCtx, "conversion", "Texture conversion tests.", populateTextureConversionTests);
440 }
441 
442 } // texture
443 } // vkt
444