1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 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  vktPipelineMultisampleTestsUtil.cpp
21 * \brief Multisample Tests Utility Classes
22 *//*--------------------------------------------------------------------*/
23
24#include "vktPipelineMultisampleTestsUtil.hpp"
25#include "vkQueryUtil.hpp"
26#include "vkTypeUtil.hpp"
27#include "tcuTextureUtil.hpp"
28
29#include <deMath.h>
30
31using namespace vk;
32
33namespace vkt
34{
35namespace pipeline
36{
37namespace multisample
38{
39
40tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize, const deUint32 mipLevel)
41{
42	const deUint32 mipLevelX = std::max(imageSize.x() >> mipLevel, 1u);
43	const deUint32 mipLevelY = std::max(imageSize.y() >> mipLevel, 1u);
44	const deUint32 mipLevelZ = std::max(imageSize.z() >> mipLevel, 1u);
45
46	switch (imageType)
47	{
48	case IMAGE_TYPE_1D:
49		return tcu::UVec3(mipLevelX, 1u, 1u);
50
51	case IMAGE_TYPE_BUFFER:
52		return tcu::UVec3(imageSize.x(), 1u, 1u);
53
54	case IMAGE_TYPE_1D_ARRAY:
55		return tcu::UVec3(mipLevelX, imageSize.z(), 1u);
56
57	case IMAGE_TYPE_2D:
58		return tcu::UVec3(mipLevelX, mipLevelY, 1u);
59
60	case IMAGE_TYPE_2D_ARRAY:
61		return tcu::UVec3(mipLevelX, mipLevelY, imageSize.z());
62
63	case IMAGE_TYPE_3D:
64		return tcu::UVec3(mipLevelX, mipLevelY, mipLevelZ);
65
66	case IMAGE_TYPE_CUBE:
67		return tcu::UVec3(mipLevelX, mipLevelY, 6u);
68
69	case IMAGE_TYPE_CUBE_ARRAY:
70		return tcu::UVec3(mipLevelX, mipLevelY, 6u * imageSize.z());
71
72	default:
73		DE_FATAL("Unknown image type");
74		return tcu::UVec3(1u, 1u, 1u);
75	}
76}
77
78tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize)
79{
80	switch (imageType)
81	{
82	case IMAGE_TYPE_1D:
83	case IMAGE_TYPE_1D_ARRAY:
84	case IMAGE_TYPE_BUFFER:
85		return tcu::UVec3(imageSize.x(), 1u, 1u);
86
87	case IMAGE_TYPE_2D:
88	case IMAGE_TYPE_2D_ARRAY:
89	case IMAGE_TYPE_CUBE:
90	case IMAGE_TYPE_CUBE_ARRAY:
91		return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
92
93	case IMAGE_TYPE_3D:
94		return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
95
96	default:
97		DE_FATAL("Unknown image type");
98		return tcu::UVec3(1u, 1u, 1u);
99	}
100}
101
102deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize)
103{
104	switch (imageType)
105	{
106	case IMAGE_TYPE_1D:
107	case IMAGE_TYPE_2D:
108	case IMAGE_TYPE_3D:
109	case IMAGE_TYPE_BUFFER:
110		return 1u;
111
112	case IMAGE_TYPE_1D_ARRAY:
113	case IMAGE_TYPE_2D_ARRAY:
114		return imageSize.z();
115
116	case IMAGE_TYPE_CUBE:
117		return 6u;
118
119	case IMAGE_TYPE_CUBE_ARRAY:
120		return imageSize.z() * 6u;
121
122	default:
123		DE_FATAL("Unknown image type");
124		return 0u;
125	}
126}
127
128deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize)
129{
130	const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize);
131
132	return gridSize.x() * gridSize.y() * gridSize.z();
133}
134
135deUint32 getDimensions (const ImageType imageType)
136{
137	switch (imageType)
138	{
139	case IMAGE_TYPE_1D:
140	case IMAGE_TYPE_BUFFER:
141		return 1u;
142
143	case IMAGE_TYPE_1D_ARRAY:
144	case IMAGE_TYPE_2D:
145		return 2u;
146
147	case IMAGE_TYPE_2D_ARRAY:
148	case IMAGE_TYPE_CUBE:
149	case IMAGE_TYPE_CUBE_ARRAY:
150	case IMAGE_TYPE_3D:
151		return 3u;
152
153	default:
154		DE_FATAL("Unknown image type");
155		return 0u;
156	}
157}
158
159deUint32 getLayerDimensions (const ImageType imageType)
160{
161	switch (imageType)
162	{
163	case IMAGE_TYPE_1D:
164	case IMAGE_TYPE_BUFFER:
165	case IMAGE_TYPE_1D_ARRAY:
166		return 1u;
167
168	case IMAGE_TYPE_2D:
169	case IMAGE_TYPE_2D_ARRAY:
170	case IMAGE_TYPE_CUBE:
171	case IMAGE_TYPE_CUBE_ARRAY:
172		return 2u;
173
174	case IMAGE_TYPE_3D:
175		return 3u;
176
177	default:
178		DE_FATAL("Unknown image type");
179		return 0u;
180	}
181}
182
183VkImageType	mapImageType (const ImageType imageType)
184{
185	switch (imageType)
186	{
187		case IMAGE_TYPE_1D:
188		case IMAGE_TYPE_1D_ARRAY:
189		case IMAGE_TYPE_BUFFER:
190			return VK_IMAGE_TYPE_1D;
191
192		case IMAGE_TYPE_2D:
193		case IMAGE_TYPE_2D_ARRAY:
194		case IMAGE_TYPE_CUBE:
195		case IMAGE_TYPE_CUBE_ARRAY:
196			return VK_IMAGE_TYPE_2D;
197
198		case IMAGE_TYPE_3D:
199			return VK_IMAGE_TYPE_3D;
200
201		default:
202			DE_ASSERT(false);
203			return VK_IMAGE_TYPE_LAST;
204	}
205}
206
207VkImageViewType	mapImageViewType (const ImageType imageType)
208{
209	switch (imageType)
210	{
211		case IMAGE_TYPE_1D:			return VK_IMAGE_VIEW_TYPE_1D;
212		case IMAGE_TYPE_1D_ARRAY:	return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
213		case IMAGE_TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
214		case IMAGE_TYPE_2D_ARRAY:	return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
215		case IMAGE_TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
216		case IMAGE_TYPE_CUBE:		return VK_IMAGE_VIEW_TYPE_CUBE;
217		case IMAGE_TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
218
219		default:
220			DE_ASSERT(false);
221			return VK_IMAGE_VIEW_TYPE_LAST;
222	}
223}
224
225std::string getImageTypeName (const ImageType imageType)
226{
227	switch (imageType)
228	{
229		case IMAGE_TYPE_1D:			return "1d";
230		case IMAGE_TYPE_1D_ARRAY:	return "1d_array";
231		case IMAGE_TYPE_2D:			return "2d";
232		case IMAGE_TYPE_2D_ARRAY:	return "2d_array";
233		case IMAGE_TYPE_3D:			return "3d";
234		case IMAGE_TYPE_CUBE:		return "cube";
235		case IMAGE_TYPE_CUBE_ARRAY:	return "cube_array";
236		case IMAGE_TYPE_BUFFER:		return "buffer";
237
238		default:
239			DE_ASSERT(false);
240			return "";
241	}
242}
243
244std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType)
245{
246	std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
247							 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
248
249	std::string imageTypePart;
250	switch (imageType)
251	{
252		case IMAGE_TYPE_1D:			imageTypePart = "1D";			break;
253		case IMAGE_TYPE_1D_ARRAY:	imageTypePart = "1DArray";		break;
254		case IMAGE_TYPE_2D:			imageTypePart = "2D";			break;
255		case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DArray";		break;
256		case IMAGE_TYPE_3D:			imageTypePart = "3D";			break;
257		case IMAGE_TYPE_CUBE:		imageTypePart = "Cube";			break;
258		case IMAGE_TYPE_CUBE_ARRAY:	imageTypePart = "CubeArray";	break;
259		case IMAGE_TYPE_BUFFER:		imageTypePart = "Buffer";		break;
260
261		default:
262			DE_ASSERT(false);
263	}
264
265	return formatPart + "image" + imageTypePart;
266}
267
268
269std::string getShaderImageDataType (const tcu::TextureFormat& format)
270{
271	switch (tcu::getTextureChannelClass(format.type))
272	{
273		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
274			return "uvec4";
275		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
276			return "ivec4";
277		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
278			return "vec4";
279		default:
280			DE_ASSERT(false);
281			return "";
282	}
283}
284
285std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
286{
287	const char* orderPart;
288	const char* typePart;
289
290	switch (format.order)
291	{
292		case tcu::TextureFormat::R:		orderPart = "r";	break;
293		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
294		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
295		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
296
297		default:
298			DE_ASSERT(false);
299			orderPart = DE_NULL;
300	}
301
302	switch (format.type)
303	{
304		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
305		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
306
307		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
308		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
309		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
310
311		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
312		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
313		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
314
315		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
316		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
317
318		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
319		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
320
321		default:
322			DE_ASSERT(false);
323			typePart = DE_NULL;
324	}
325
326	return std::string() + orderPart + typePart;
327}
328
329std::string getShaderImageCoordinates	(const ImageType	imageType,
330										 const std::string&	x,
331										 const std::string&	xy,
332										 const std::string&	xyz)
333{
334	switch (imageType)
335	{
336		case IMAGE_TYPE_1D:
337		case IMAGE_TYPE_BUFFER:
338			return x;
339
340		case IMAGE_TYPE_1D_ARRAY:
341		case IMAGE_TYPE_2D:
342			return xy;
343
344		case IMAGE_TYPE_2D_ARRAY:
345		case IMAGE_TYPE_3D:
346		case IMAGE_TYPE_CUBE:
347		case IMAGE_TYPE_CUBE_ARRAY:
348			return xyz;
349
350		default:
351			DE_ASSERT(0);
352			return "";
353	}
354}
355
356VkExtent3D mipLevelExtents (const VkExtent3D& baseExtents, const deUint32 mipLevel)
357{
358	VkExtent3D result;
359
360	result.width	= std::max(baseExtents.width  >> mipLevel, 1u);
361	result.height	= std::max(baseExtents.height >> mipLevel, 1u);
362	result.depth	= std::max(baseExtents.depth  >> mipLevel, 1u);
363
364	return result;
365}
366
367deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatProperties, const VkExtent3D& extent)
368{
369	const deUint32 widestEdge = std::max(std::max(extent.width, extent.height), extent.depth);
370
371	return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, imageFormatProperties.maxMipLevels);
372}
373
374deUint32 getImageMipLevelSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 numSamples)
375{
376	const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
377
378	return extents.width * extents.height * extents.depth * layersCount * numSamples * tcu::getPixelSize(format);
379}
380
381deUint32 getImageSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 numSamples)
382{
383	deUint32 imageSizeInBytes = 0;
384	for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
385	{
386		imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, numSamples);
387	}
388
389	return imageSizeInBytes;
390}
391
392void requireFeatures (const InstanceInterface& instanceInterface, const VkPhysicalDevice physicalDevice, const FeatureFlags flags)
393{
394	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(instanceInterface, physicalDevice);
395
396	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
397		throw tcu::NotSupportedError("Tessellation shader not supported");
398
399	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
400		throw tcu::NotSupportedError("Geometry shader not supported");
401
402	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
403		throw tcu::NotSupportedError("Double-precision floats not supported");
404
405	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
406		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
407
408	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
409		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
410
411	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
412		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
413}
414
415} // multisample
416} // pipeline
417} // vkt
418