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 
31 using namespace vk;
32 
33 namespace vkt
34 {
35 namespace pipeline
36 {
37 namespace multisample
38 {
39 
getShaderGridSize(const ImageType imageType,const tcu::UVec3 & imageSize,const uint32_t mipLevel)40 tcu::UVec3 getShaderGridSize(const ImageType imageType, const tcu::UVec3 &imageSize, const uint32_t mipLevel)
41 {
42     const uint32_t mipLevelX = std::max(imageSize.x() >> mipLevel, 1u);
43     const uint32_t mipLevelY = std::max(imageSize.y() >> mipLevel, 1u);
44     const uint32_t 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 
getLayerSize(const ImageType imageType,const tcu::UVec3 & imageSize)78 tcu::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 
getNumLayers(const ImageType imageType,const tcu::UVec3 & imageSize)102 uint32_t 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 
getNumPixels(const ImageType imageType,const tcu::UVec3 & imageSize)128 uint32_t 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 
getDimensions(const ImageType imageType)135 uint32_t 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 
getLayerDimensions(const ImageType imageType)159 uint32_t 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 
mapImageType(const ImageType imageType)183 VkImageType 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 
mapImageViewType(const ImageType imageType)207 VkImageViewType mapImageViewType(const ImageType imageType)
208 {
209     switch (imageType)
210     {
211     case IMAGE_TYPE_1D:
212         return VK_IMAGE_VIEW_TYPE_1D;
213     case IMAGE_TYPE_1D_ARRAY:
214         return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
215     case IMAGE_TYPE_2D:
216         return VK_IMAGE_VIEW_TYPE_2D;
217     case IMAGE_TYPE_2D_ARRAY:
218         return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
219     case IMAGE_TYPE_3D:
220         return VK_IMAGE_VIEW_TYPE_3D;
221     case IMAGE_TYPE_CUBE:
222         return VK_IMAGE_VIEW_TYPE_CUBE;
223     case IMAGE_TYPE_CUBE_ARRAY:
224         return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
225 
226     default:
227         DE_ASSERT(false);
228         return VK_IMAGE_VIEW_TYPE_LAST;
229     }
230 }
231 
getImageTypeName(const ImageType imageType)232 std::string getImageTypeName(const ImageType imageType)
233 {
234     switch (imageType)
235     {
236     case IMAGE_TYPE_1D:
237         return "1d";
238     case IMAGE_TYPE_1D_ARRAY:
239         return "1d_array";
240     case IMAGE_TYPE_2D:
241         return "2d";
242     case IMAGE_TYPE_2D_ARRAY:
243         return "2d_array";
244     case IMAGE_TYPE_3D:
245         return "3d";
246     case IMAGE_TYPE_CUBE:
247         return "cube";
248     case IMAGE_TYPE_CUBE_ARRAY:
249         return "cube_array";
250     case IMAGE_TYPE_BUFFER:
251         return "buffer";
252 
253     default:
254         DE_ASSERT(false);
255         return "";
256     }
257 }
258 
getShaderImageType(const tcu::TextureFormat & format,const ImageType imageType)259 std::string getShaderImageType(const tcu::TextureFormat &format, const ImageType imageType)
260 {
261     std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ?
262                                  "u" :
263                              tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" :
264                                                                                                                    "";
265 
266     std::string imageTypePart;
267     switch (imageType)
268     {
269     case IMAGE_TYPE_1D:
270         imageTypePart = "1D";
271         break;
272     case IMAGE_TYPE_1D_ARRAY:
273         imageTypePart = "1DArray";
274         break;
275     case IMAGE_TYPE_2D:
276         imageTypePart = "2D";
277         break;
278     case IMAGE_TYPE_2D_ARRAY:
279         imageTypePart = "2DArray";
280         break;
281     case IMAGE_TYPE_3D:
282         imageTypePart = "3D";
283         break;
284     case IMAGE_TYPE_CUBE:
285         imageTypePart = "Cube";
286         break;
287     case IMAGE_TYPE_CUBE_ARRAY:
288         imageTypePart = "CubeArray";
289         break;
290     case IMAGE_TYPE_BUFFER:
291         imageTypePart = "Buffer";
292         break;
293 
294     default:
295         DE_ASSERT(false);
296     }
297 
298     return formatPart + "image" + imageTypePart;
299 }
300 
getShaderImageDataType(const tcu::TextureFormat & format)301 std::string getShaderImageDataType(const tcu::TextureFormat &format)
302 {
303     switch (tcu::getTextureChannelClass(format.type))
304     {
305     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
306         return "uvec4";
307     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
308         return "ivec4";
309     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
310         return "vec4";
311     default:
312         DE_ASSERT(false);
313         return "";
314     }
315 }
316 
getShaderImageFormatQualifier(const tcu::TextureFormat & format)317 std::string getShaderImageFormatQualifier(const tcu::TextureFormat &format)
318 {
319     const char *orderPart;
320     const char *typePart;
321 
322     switch (format.order)
323     {
324     case tcu::TextureFormat::R:
325         orderPart = "r";
326         break;
327     case tcu::TextureFormat::RG:
328         orderPart = "rg";
329         break;
330     case tcu::TextureFormat::RGB:
331         orderPart = "rgb";
332         break;
333     case tcu::TextureFormat::RGBA:
334         orderPart = "rgba";
335         break;
336 
337     default:
338         DE_ASSERT(false);
339         orderPart = DE_NULL;
340     }
341 
342     switch (format.type)
343     {
344     case tcu::TextureFormat::FLOAT:
345         typePart = "32f";
346         break;
347     case tcu::TextureFormat::HALF_FLOAT:
348         typePart = "16f";
349         break;
350 
351     case tcu::TextureFormat::UNSIGNED_INT32:
352         typePart = "32ui";
353         break;
354     case tcu::TextureFormat::UNSIGNED_INT16:
355         typePart = "16ui";
356         break;
357     case tcu::TextureFormat::UNSIGNED_INT8:
358         typePart = "8ui";
359         break;
360 
361     case tcu::TextureFormat::SIGNED_INT32:
362         typePart = "32i";
363         break;
364     case tcu::TextureFormat::SIGNED_INT16:
365         typePart = "16i";
366         break;
367     case tcu::TextureFormat::SIGNED_INT8:
368         typePart = "8i";
369         break;
370 
371     case tcu::TextureFormat::UNORM_INT16:
372         typePart = "16";
373         break;
374     case tcu::TextureFormat::UNORM_INT8:
375         typePart = "8";
376         break;
377 
378     case tcu::TextureFormat::SNORM_INT16:
379         typePart = "16_snorm";
380         break;
381     case tcu::TextureFormat::SNORM_INT8:
382         typePart = "8_snorm";
383         break;
384 
385     default:
386         DE_ASSERT(false);
387         typePart = DE_NULL;
388     }
389 
390     return std::string() + orderPart + typePart;
391 }
392 
getShaderImageCoordinates(const ImageType imageType,const std::string & x,const std::string & xy,const std::string & xyz)393 std::string getShaderImageCoordinates(const ImageType imageType, const std::string &x, const std::string &xy,
394                                       const std::string &xyz)
395 {
396     switch (imageType)
397     {
398     case IMAGE_TYPE_1D:
399     case IMAGE_TYPE_BUFFER:
400         return x;
401 
402     case IMAGE_TYPE_1D_ARRAY:
403     case IMAGE_TYPE_2D:
404         return xy;
405 
406     case IMAGE_TYPE_2D_ARRAY:
407     case IMAGE_TYPE_3D:
408     case IMAGE_TYPE_CUBE:
409     case IMAGE_TYPE_CUBE_ARRAY:
410         return xyz;
411 
412     default:
413         DE_ASSERT(0);
414         return "";
415     }
416 }
417 
getImageMaxMipLevels(const VkImageFormatProperties & imageFormatProperties,const VkExtent3D & extent)418 uint32_t getImageMaxMipLevels(const VkImageFormatProperties &imageFormatProperties, const VkExtent3D &extent)
419 {
420     const uint32_t widestEdge = std::max(std::max(extent.width, extent.height), extent.depth);
421 
422     return std::min(static_cast<uint32_t>(deFloatLog2(static_cast<float>(widestEdge))) + 1u,
423                     imageFormatProperties.maxMipLevels);
424 }
425 
getImageMipLevelSizeInBytes(const VkExtent3D & baseExtents,const uint32_t layersCount,const tcu::TextureFormat & format,const uint32_t mipmapLevel,const uint32_t numSamples)426 uint32_t getImageMipLevelSizeInBytes(const VkExtent3D &baseExtents, const uint32_t layersCount,
427                                      const tcu::TextureFormat &format, const uint32_t mipmapLevel,
428                                      const uint32_t numSamples)
429 {
430     const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
431 
432     return extents.width * extents.height * extents.depth * layersCount * numSamples * tcu::getPixelSize(format);
433 }
434 
getImageSizeInBytes(const VkExtent3D & baseExtents,const uint32_t layersCount,const tcu::TextureFormat & format,const uint32_t mipmapLevelsCount,const uint32_t numSamples)435 uint32_t getImageSizeInBytes(const VkExtent3D &baseExtents, const uint32_t layersCount,
436                              const tcu::TextureFormat &format, const uint32_t mipmapLevelsCount,
437                              const uint32_t numSamples)
438 {
439     uint32_t imageSizeInBytes = 0;
440     for (uint32_t mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
441     {
442         imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, numSamples);
443     }
444 
445     return imageSizeInBytes;
446 }
447 
requireFeatures(const InstanceInterface & instanceInterface,const VkPhysicalDevice physicalDevice,const FeatureFlags flags)448 void requireFeatures(const InstanceInterface &instanceInterface, const VkPhysicalDevice physicalDevice,
449                      const FeatureFlags flags)
450 {
451     const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(instanceInterface, physicalDevice);
452 
453     if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
454         throw tcu::NotSupportedError("Tessellation shader not supported");
455 
456     if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
457         throw tcu::NotSupportedError("Geometry shader not supported");
458 
459     if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
460         throw tcu::NotSupportedError("Double-precision floats not supported");
461 
462     if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
463         throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
464 
465     if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
466         throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
467 
468     if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) &&
469         !features.shaderTessellationAndGeometryPointSize)
470         throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
471 }
472 
473 } // namespace multisample
474 } // namespace pipeline
475 } // namespace vkt
476