1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Image View Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineImageViewTests.hpp"
28 #include "vktPipelineImageSamplingInstance.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktTestCase.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "tcuPlatform.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "deStringUtil.hpp"
37 #include "deMemory.h"
38
39 #include <sstream>
40 #include <vector>
41
42 namespace vkt
43 {
44 namespace pipeline
45 {
46
47 using namespace vk;
48 using de::MovePtr;
49
50 namespace
51 {
52
53
54 class ImageViewTest : public vkt::TestCase
55 {
56 public:
57 ImageViewTest (tcu::TestContext& testContext,
58 const char* name,
59 PipelineConstructionType pipelineConstructionType,
60 VkImageViewType imageViewType,
61 VkFormat imageFormat,
62 float samplerLod,
63 const VkComponentMapping& componentMapping,
64 const VkImageSubresourceRange& subresourceRange);
~ImageViewTest(void)65 virtual ~ImageViewTest (void) {}
66
67 ImageSamplingInstanceParams getImageSamplingInstanceParams (VkImageViewType imageViewType,
68 VkFormat imageFormat,
69 float samplerLod,
70 const VkComponentMapping& componentMapping,
71 const VkImageSubresourceRange& subresourceRange) const;
72
73 virtual void initPrograms (SourceCollections& sourceCollections) const;
74 virtual void checkSupport (Context& context) const;
75 virtual TestInstance* createInstance (Context& context) const;
76 static std::string getGlslSamplerType (const tcu::TextureFormat& format,
77 VkImageViewType type);
78 static tcu::UVec2 getRenderSize (VkImageViewType viewType);
79 static tcu::IVec3 getImageSize (VkImageViewType viewType);
80 static int getArraySize (VkImageViewType viewType);
81 static int getNumLevels (VkImageViewType viewType);
82 static tcu::Vec4 swizzle (tcu::Vec4 inputData,
83 VkComponentMapping componentMapping);
84 private:
85 PipelineConstructionType m_pipelineConstructionType;
86 VkImageViewType m_imageViewType;
87 VkFormat m_imageFormat;
88 float m_samplerLod;
89 VkComponentMapping m_componentMapping;
90 VkImageSubresourceRange m_subresourceRange;
91 };
92
ImageViewTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,VkImageViewType imageViewType,VkFormat imageFormat,float samplerLod,const VkComponentMapping & componentMapping,const VkImageSubresourceRange & subresourceRange)93 ImageViewTest::ImageViewTest (tcu::TestContext& testContext,
94 const char* name,
95 PipelineConstructionType pipelineConstructionType,
96 VkImageViewType imageViewType,
97 VkFormat imageFormat,
98 float samplerLod,
99 const VkComponentMapping& componentMapping,
100 const VkImageSubresourceRange& subresourceRange)
101
102 : vkt::TestCase (testContext, name)
103 , m_pipelineConstructionType (pipelineConstructionType)
104 , m_imageViewType (imageViewType)
105 , m_imageFormat (imageFormat)
106 , m_samplerLod (samplerLod)
107 , m_componentMapping (componentMapping)
108 , m_subresourceRange (subresourceRange)
109 {
110 }
111
getImageSamplingInstanceParams(VkImageViewType imageViewType,VkFormat imageFormat,float samplerLod,const VkComponentMapping & componentMapping,const VkImageSubresourceRange & subresourceRange) const112 ImageSamplingInstanceParams ImageViewTest::getImageSamplingInstanceParams (VkImageViewType imageViewType,
113 VkFormat imageFormat,
114 float samplerLod,
115 const VkComponentMapping& componentMapping,
116 const VkImageSubresourceRange& subresourceRange) const
117 {
118 const tcu::UVec2 renderSize = getRenderSize(imageViewType);
119 const tcu::IVec3 imageSize = getImageSize(imageViewType);
120 const int arraySize = getArraySize(imageViewType);
121 const std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(imageViewType);
122
123 const VkSamplerCreateInfo samplerParams =
124 {
125 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
126 DE_NULL, // const void* pNext;
127 0u, // VkSamplerCreateFlags flags;
128 VK_FILTER_NEAREST, // VkFilter magFilter;
129 VK_FILTER_NEAREST, // VkFilter minFilter;
130 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
131 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
132 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
133 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
134 0.0f, // float mipLodBias;
135 VK_FALSE, // VkBool32 anisotropyEnable;
136 1.0f, // float maxAnisotropy;
137 false, // VkBool32 compareEnable;
138 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
139 0.0f, // float minLod;
140 (float)(subresourceRange.levelCount - 1), // float maxLod;
141 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, imageFormat, false), // VkBorderColor borderColor;
142 false // VkBool32 unnormalizedCoordinates;
143 };
144
145 return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat, imageSize, arraySize, componentMapping, subresourceRange, samplerParams, samplerLod, vertices);
146 }
147
checkSupport(Context & context) const148 void ImageViewTest::checkSupport (Context& context) const
149 {
150 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
151
152 #ifndef CTS_USES_VULKANSC
153 if (m_imageFormat == VK_FORMAT_A8_UNORM_KHR || m_imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
154 context.requireDeviceFunctionality("VK_KHR_maintenance5");
155 #endif // CTS_USES_VULKANSC
156
157 checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_samplerLod, m_componentMapping, m_subresourceRange));
158 }
159
swizzle(tcu::Vec4 inputData,VkComponentMapping componentMapping)160 tcu::Vec4 ImageViewTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping)
161 {
162 // array map with enum VkComponentSwizzle
163 const float channelValues[] =
164 {
165 -1.0f,
166 0.0f,
167 1.0f,
168 inputData.x(),
169 inputData.y(),
170 inputData.z(),
171 inputData.w(),
172 -1.0f
173 };
174
175 return tcu::Vec4(channelValues[componentMapping.r],
176 channelValues[componentMapping.g],
177 channelValues[componentMapping.b],
178 channelValues[componentMapping.a]);
179 }
180
initPrograms(SourceCollections & sourceCollections) const181 void ImageViewTest::initPrograms (SourceCollections& sourceCollections) const
182 {
183 std::ostringstream vertexSrc;
184 std::ostringstream fragmentSrc;
185 const char* texCoordSwizzle = DE_NULL;
186 const tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
187 : mapVkFormat(m_imageFormat);
188
189 tcu::Vec4 lookupScale;
190 tcu::Vec4 lookupBias;
191
192 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
193
194 tcu::Vec4 swizzledScale = swizzle(lookupScale, m_componentMapping);
195 tcu::Vec4 swizzledBias = swizzle(lookupBias, m_componentMapping);
196
197 switch (m_imageViewType)
198 {
199 case VK_IMAGE_VIEW_TYPE_1D:
200 texCoordSwizzle = "x";
201 break;
202 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
203 case VK_IMAGE_VIEW_TYPE_2D:
204 texCoordSwizzle = "xy";
205 break;
206 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
207 case VK_IMAGE_VIEW_TYPE_3D:
208 case VK_IMAGE_VIEW_TYPE_CUBE:
209 texCoordSwizzle = "xyz";
210 break;
211 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
212 texCoordSwizzle = "xyzw";
213 break;
214 default:
215 DE_ASSERT(false);
216 break;
217 }
218
219 vertexSrc << "#version 440\n"
220 << "layout(location = 0) in vec4 position;\n"
221 << "layout(location = 1) in vec4 texCoords;\n"
222 << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
223 << "out gl_PerVertex {\n"
224 << " vec4 gl_Position;\n"
225 << "};\n"
226 << "void main (void)\n"
227 << "{\n"
228 << " gl_Position = position;\n"
229 << " vtxTexCoords = texCoords;\n"
230 << "}\n";
231
232 fragmentSrc << "#version 440\n"
233 << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
234 << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
235 << "layout(location = 0) out highp vec4 fragColor;\n"
236 << "void main (void)\n"
237 << "{\n"
238 << " fragColor = ";
239
240 if (m_samplerLod > 0.0f)
241 fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
242 else
243 fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
244
245 fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
246 << "}\n";
247
248 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
249 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
250 }
251
createInstance(Context & context) const252 TestInstance* ImageViewTest::createInstance (Context& context) const
253 {
254 return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_samplerLod, m_componentMapping, m_subresourceRange));
255 }
256
getGlslSamplerType(const tcu::TextureFormat & format,VkImageViewType type)257 std::string ImageViewTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
258 {
259 std::ostringstream samplerType;
260
261 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
262 samplerType << "u";
263 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
264 samplerType << "i";
265
266 switch (type)
267 {
268 case VK_IMAGE_VIEW_TYPE_1D:
269 samplerType << "sampler1D";
270 break;
271
272 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
273 samplerType << "sampler1DArray";
274 break;
275
276 case VK_IMAGE_VIEW_TYPE_2D:
277 samplerType << "sampler2D";
278 break;
279
280 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
281 samplerType << "sampler2DArray";
282 break;
283
284 case VK_IMAGE_VIEW_TYPE_3D:
285 samplerType << "sampler3D";
286 break;
287
288 case VK_IMAGE_VIEW_TYPE_CUBE:
289 samplerType << "samplerCube";
290 break;
291
292 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
293 samplerType << "samplerCubeArray";
294 break;
295
296 default:
297 DE_FATAL("Unknown image view type");
298 break;
299 }
300
301 return samplerType.str();
302 }
303
getRenderSize(VkImageViewType viewType)304 tcu::UVec2 ImageViewTest::getRenderSize (VkImageViewType viewType)
305 {
306 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
307 return tcu::UVec2(16u, 16u);
308 else
309 return tcu::UVec2(16u * 3u, 16u * 2u);
310 }
311
getImageSize(VkImageViewType viewType)312 tcu::IVec3 ImageViewTest::getImageSize (VkImageViewType viewType)
313 {
314 switch (viewType)
315 {
316 case VK_IMAGE_VIEW_TYPE_1D:
317 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
318 return tcu::IVec3(16, 1, 1);
319
320 case VK_IMAGE_VIEW_TYPE_3D:
321 return tcu::IVec3(16);
322
323 default:
324 break;
325 }
326
327 return tcu::IVec3(16, 16, 1);
328 }
329
getArraySize(VkImageViewType viewType)330 int ImageViewTest::getArraySize (VkImageViewType viewType)
331 {
332 switch (viewType)
333 {
334 case VK_IMAGE_VIEW_TYPE_3D:
335 return 1;
336
337 case VK_IMAGE_VIEW_TYPE_CUBE:
338 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
339 return 18;
340
341 default:
342 break;
343 }
344
345 return 6;
346 }
347
getNumLevels(VkImageViewType viewType)348 int ImageViewTest::getNumLevels (VkImageViewType viewType)
349 {
350 const tcu::IVec3 imageSize = getImageSize(viewType);
351
352 return deLog2Floor32(deMax32(imageSize.x(), deMax32(imageSize.y(), imageSize.z()))) + 1;
353 }
354
getFormatCaseName(const VkFormat format)355 static std::string getFormatCaseName (const VkFormat format)
356 {
357 const std::string fullName = getFormatName(format);
358
359 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
360
361 return de::toLower(fullName.substr(10));
362 }
363
createSubresourceRangeTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,VkImageViewType viewType,VkFormat imageFormat)364 static de::MovePtr<tcu::TestCaseGroup> createSubresourceRangeTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, VkImageViewType viewType, VkFormat imageFormat)
365 {
366 struct TestCaseConfig
367 {
368 const char* name;
369 float samplerLod;
370 VkImageSubresourceRange subresourceRange;
371 };
372
373 const deUint32 numLevels = ImageViewTest::getNumLevels(viewType);
374 const deUint32 arraySize = ImageViewTest::getArraySize(viewType);
375 const VkImageAspectFlags imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
376 const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
377
378 de::MovePtr<tcu::TestCaseGroup> rangeTests (new tcu::TestCaseGroup(testCtx, "subresource_range"));
379
380 #define ADD_SUBRESOURCE_RANGE_TESTS(TEST_CASES) \
381 do { \
382 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(TEST_CASES); configNdx++) \
383 { \
384 const TestCaseConfig config = (TEST_CASES)[configNdx]; \
385 rangeTests->addChild(new ImageViewTest(testCtx, config.name, \
386 pipelineConstructionType,viewType, imageFormat, \
387 config.samplerLod, componentMapping, \
388 config.subresourceRange)); \
389 } \
390 } while (deGetFalse())
391
392 if (viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
393 {
394 const TestCaseConfig mipLevelRangeCases[] =
395 {
396 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
397 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
398 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } },
399 };
400
401 const TestCaseConfig arrayRangeCases[] =
402 {
403 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
404 { "base_array_layer", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, arraySize - 1u } },
405 { "array_size", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, 4u } },
406 { "array_base_and_size", 0.0f, { imageAspectFlags, 0u, numLevels, 2u, 3u } },
407 };
408
409 const TestCaseConfig mipLevelAndArrayRangeCases[] =
410 {
411 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
412 { "lod_base_mip_level_base_array_layer", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 1u, 5u } },
413 { "lod_mip_levels_base_array_layer", 4.0f, { imageAspectFlags, 0u, 3u, 1u, 5u } },
414
415 { "lod_base_mip_level_array_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 4u } },
416 { "lod_mip_levels_array_size", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 4u } },
417
418 { "lod_base_mip_level_array_base_and_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 2u, 3u } },
419 { "lod_mip_levels_array_base_and_size", 4.0f, { imageAspectFlags, 0u, 3u, 2u, 3u } },
420 };
421
422 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
423 {
424 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
425 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, arraySize } },
426 { "base_array_layer_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, VK_REMAINING_ARRAY_LAYERS } },
427 { "lod_base_mip_level_base_array_layer_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, 2u, VK_REMAINING_ARRAY_LAYERS } },
428 };
429
430 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
431 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
432 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
433 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
434 }
435 else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
436 {
437 const TestCaseConfig mipLevelRangeCases[] =
438 {
439 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
440 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
441 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } },
442 };
443
444 const TestCaseConfig arrayRangeCases[] =
445 {
446 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
447 { "base_array_layer", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, arraySize - 6u } },
448 { "array_size", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, 6u } },
449 { "array_base_and_size", 0.0f, { imageAspectFlags, 0u, numLevels, 12u, 6u } },
450 };
451
452 const TestCaseConfig mipLevelAndArrayRangeCases[] =
453 {
454 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
455 { "lod_base_mip_level_base_array_layer", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 6u, arraySize - 6u } },
456 { "lod_mip_levels_base_array_layer", 4.0f, { imageAspectFlags, 0u, 3u, 6u, arraySize - 6u } },
457
458 { "lod_base_mip_level_array_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
459 { "lod_mip_levels_array_size", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 6u } },
460
461 { "lod_base_mip_level_array_base_and_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 12u, 6u } },
462 { "lod_mip_levels_array_base_and_size", 4.0f, { imageAspectFlags, 0u, 3u, 12u, 6u } },
463 };
464
465 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
466 {
467 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
468 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, arraySize } },
469 { "base_array_layer_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, VK_REMAINING_ARRAY_LAYERS } },
470 { "lod_base_mip_level_base_array_layer_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, 12u, VK_REMAINING_ARRAY_LAYERS } },
471 };
472
473 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
474 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
475 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
476 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
477 }
478 else if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
479 {
480 const TestCaseConfig mipLevelRangeCases[] =
481 {
482 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
483 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 1u } },
484 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 1u } },
485 };
486
487 const TestCaseConfig arrayRangeCases[] =
488 {
489 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
490 { "array_layer_second", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, 1u } },
491 { "array_layer_last", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 1u, 1u } },
492 };
493
494 const TestCaseConfig mipLevelAndArrayRangeCases[] =
495 {
496 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
497 { "lod_base_mip_level_array_layer_second", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 1u, 1u } },
498 { "lod_mip_levels_array_layer_second", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
499
500 { "lod_base_mip_level_array_layer_last", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 5u, 1u } },
501 { "lod_mip_levels_array_layer_last", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
502 };
503
504 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
505 {
506 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
507 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, 1u } },
508 { "array_layer_last_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 1u, VK_REMAINING_ARRAY_LAYERS } },
509 { "lod_base_mip_level_array_layer_last_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, arraySize - 1u, VK_REMAINING_ARRAY_LAYERS } },
510 };
511
512 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
513 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
514 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
515 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
516 }
517 else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE)
518 {
519 const TestCaseConfig mipLevelRangeCases[] =
520 {
521 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
522 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
523 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 6u } },
524 };
525
526 const TestCaseConfig arrayRangeCases[] =
527 {
528 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
529 { "array_layer_second", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, 6u } },
530 { "array_layer_last", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 6u, 6u } },
531 };
532
533 const TestCaseConfig mipLevelAndArrayRangeCases[] =
534 {
535 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
536 { "lod_base_mip_level_array_layer_second", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 6u, 6u } },
537 { "lod_mip_levels_array_layer_second", 4.0f, { imageAspectFlags, 0u, 3u, 6u, 6u } },
538
539 { "lod_base_mip_level_array_layer_last", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, arraySize - 6u, 6u } },
540 { "lod_mip_levels_array_layer_last", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 6u, 6u } },
541 };
542
543 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
544 {
545 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
546 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, 6u } },
547 { "array_layer_last_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 6u, VK_REMAINING_ARRAY_LAYERS } },
548 { "lod_base_mip_level_array_layer_last_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, arraySize - 6u, VK_REMAINING_ARRAY_LAYERS } },
549 };
550
551 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
552 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
553 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
554 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
555 }
556 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
557 {
558 const TestCaseConfig mipLevelRangeCases[] =
559 {
560 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
561 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
562 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } },
563 };
564
565 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
566 {
567 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
568 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, arraySize } },
569 { "single_array_layer_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, VK_REMAINING_ARRAY_LAYERS } },
570 { "lod_base_mip_level_single_array_layer_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS } },
571 };
572
573 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
574 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
575 }
576
577 #undef ADD_SUBRESOURCE_RANGE_TESTS
578
579 return rangeTests;
580 }
581
getComponentMappingPermutations(const VkComponentMapping & componentMapping)582 static std::vector<VkComponentMapping> getComponentMappingPermutations (const VkComponentMapping& componentMapping)
583 {
584 std::vector<VkComponentMapping> mappings;
585
586 const VkComponentSwizzle channelSwizzles[4] = { componentMapping.r, componentMapping.g, componentMapping.b, componentMapping.a };
587
588 // Rearranges the channels by shifting their positions.
589 for (int firstChannelNdx = 0; firstChannelNdx < 4; firstChannelNdx++)
590 {
591 VkComponentSwizzle currentChannel[4];
592
593 for (int channelNdx = 0; channelNdx < 4; channelNdx++)
594 currentChannel[channelNdx] = channelSwizzles[(firstChannelNdx + channelNdx) % 4];
595
596 const VkComponentMapping mappingPermutation =
597 {
598 currentChannel[0],
599 currentChannel[1],
600 currentChannel[2],
601 currentChannel[3]
602 };
603
604 mappings.push_back(mappingPermutation);
605 }
606
607 return mappings;
608 }
609
getComponentSwizzleCaseName(VkComponentSwizzle componentSwizzle)610 static std::string getComponentSwizzleCaseName (VkComponentSwizzle componentSwizzle)
611 {
612 const std::string fullName = getComponentSwizzleName(componentSwizzle);
613
614 DE_ASSERT(de::beginsWith(fullName, "VK_COMPONENT_SWIZZLE_"));
615
616 return de::toLower(fullName.substr(21));
617 }
618
getComponentMappingCaseName(const VkComponentMapping & componentMapping)619 static std::string getComponentMappingCaseName (const VkComponentMapping& componentMapping)
620 {
621 std::ostringstream name;
622
623 name << getComponentSwizzleCaseName(componentMapping.r) << "_"
624 << getComponentSwizzleCaseName(componentMapping.g) << "_"
625 << getComponentSwizzleCaseName(componentMapping.b) << "_"
626 << getComponentSwizzleCaseName(componentMapping.a);
627
628 return name.str();
629 }
630
createComponentSwizzleTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,VkImageViewType viewType,VkFormat imageFormat)631 static de::MovePtr<tcu::TestCaseGroup> createComponentSwizzleTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, VkImageViewType viewType, VkFormat imageFormat)
632 {
633 deUint32 arraySize = 0;
634
635 switch (viewType)
636 {
637 case VK_IMAGE_VIEW_TYPE_1D:
638 case VK_IMAGE_VIEW_TYPE_2D:
639 case VK_IMAGE_VIEW_TYPE_3D:
640 arraySize = 1;
641 break;
642
643 case VK_IMAGE_VIEW_TYPE_CUBE:
644 arraySize = 6;
645 break;
646
647 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
648 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
649 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
650 arraySize = ImageViewTest::getArraySize(viewType);
651 break;
652
653 default:
654 break;
655 }
656
657 const VkImageSubresourceRange subresourceRange =
658 {
659 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
660 0u, // deUint32 baseMipLevel;
661 (deUint32)ImageViewTest::getNumLevels(viewType), // deUint32 mipLevels;
662 0u, // deUint32 baseArrayLayer;
663 arraySize, // deUint32 arraySize;
664 };
665
666 const VkComponentMapping baseMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
667 const std::vector<VkComponentMapping> componentMappings = getComponentMappingPermutations(baseMapping);
668 de::MovePtr<tcu::TestCaseGroup> swizzleTests (new tcu::TestCaseGroup(testCtx, "component_swizzle"));
669
670 for (size_t mappingNdx = 0; mappingNdx < componentMappings.size(); mappingNdx++)
671 {
672 swizzleTests->addChild(new ImageViewTest(testCtx,
673 getComponentMappingCaseName(componentMappings[mappingNdx]).c_str(),
674 pipelineConstructionType,
675 viewType,
676 imageFormat,
677 0.0f,
678 componentMappings[mappingNdx],
679 subresourceRange));
680 }
681
682 return swizzleTests;
683 }
684
685 } // anonymous
686
createImageViewTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)687 tcu::TestCaseGroup* createImageViewTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
688 {
689 const struct
690 {
691 VkImageViewType type;
692 const char* name;
693 }
694 imageViewTypes[] =
695 {
696 { VK_IMAGE_VIEW_TYPE_1D, "1d" },
697 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
698 { VK_IMAGE_VIEW_TYPE_2D, "2d" },
699 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
700 { VK_IMAGE_VIEW_TYPE_3D, "3d" },
701 { VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
702 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
703 };
704
705 const VkFormat formats[] =
706 {
707 VK_FORMAT_R4G4_UNORM_PACK8,
708 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
709 VK_FORMAT_R5G6B5_UNORM_PACK16,
710 VK_FORMAT_R5G5B5A1_UNORM_PACK16,
711 #ifndef CTS_USES_VULKANSC
712 VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
713 #endif // CTS_USES_VULKANSC
714 VK_FORMAT_R8_UNORM,
715 VK_FORMAT_R8_SNORM,
716 VK_FORMAT_R8_USCALED,
717 VK_FORMAT_R8_SSCALED,
718 VK_FORMAT_R8_UINT,
719 VK_FORMAT_R8_SINT,
720 VK_FORMAT_R8_SRGB,
721 #ifndef CTS_USES_VULKANSC
722 VK_FORMAT_A8_UNORM_KHR,
723 #endif // CTS_USES_VULKANSC
724 VK_FORMAT_R8G8_UNORM,
725 VK_FORMAT_R8G8_SNORM,
726 VK_FORMAT_R8G8_USCALED,
727 VK_FORMAT_R8G8_SSCALED,
728 VK_FORMAT_R8G8_UINT,
729 VK_FORMAT_R8G8_SINT,
730 VK_FORMAT_R8G8_SRGB,
731 VK_FORMAT_R8G8B8_UNORM,
732 VK_FORMAT_R8G8B8_SNORM,
733 VK_FORMAT_R8G8B8_USCALED,
734 VK_FORMAT_R8G8B8_SSCALED,
735 VK_FORMAT_R8G8B8_UINT,
736 VK_FORMAT_R8G8B8_SINT,
737 VK_FORMAT_R8G8B8_SRGB,
738 VK_FORMAT_B8G8R8_UNORM,
739 VK_FORMAT_B8G8R8_SNORM,
740 VK_FORMAT_B8G8R8_USCALED,
741 VK_FORMAT_B8G8R8_SSCALED,
742 VK_FORMAT_B8G8R8_UINT,
743 VK_FORMAT_B8G8R8_SINT,
744 VK_FORMAT_B8G8R8_SRGB,
745 VK_FORMAT_R8G8B8A8_UNORM,
746 VK_FORMAT_R8G8B8A8_SNORM,
747 VK_FORMAT_R8G8B8A8_USCALED,
748 VK_FORMAT_R8G8B8A8_SSCALED,
749 VK_FORMAT_R8G8B8A8_UINT,
750 VK_FORMAT_R8G8B8A8_SINT,
751 VK_FORMAT_R8G8B8A8_SRGB,
752 VK_FORMAT_B8G8R8A8_UNORM,
753 VK_FORMAT_B8G8R8A8_SNORM,
754 VK_FORMAT_B8G8R8A8_USCALED,
755 VK_FORMAT_B8G8R8A8_SSCALED,
756 VK_FORMAT_B8G8R8A8_UINT,
757 VK_FORMAT_B8G8R8A8_SINT,
758 VK_FORMAT_B8G8R8A8_SRGB,
759 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
760 VK_FORMAT_A2R10G10B10_UINT_PACK32,
761 VK_FORMAT_A2B10G10R10_USCALED_PACK32,
762 VK_FORMAT_R16_UNORM,
763 VK_FORMAT_R16_SNORM,
764 VK_FORMAT_R16_USCALED,
765 VK_FORMAT_R16_SSCALED,
766 VK_FORMAT_R16_UINT,
767 VK_FORMAT_R16_SINT,
768 VK_FORMAT_R16_SFLOAT,
769 VK_FORMAT_R16G16_UNORM,
770 VK_FORMAT_R16G16_SNORM,
771 VK_FORMAT_R16G16_USCALED,
772 VK_FORMAT_R16G16_SSCALED,
773 VK_FORMAT_R16G16_UINT,
774 VK_FORMAT_R16G16_SINT,
775 VK_FORMAT_R16G16_SFLOAT,
776 VK_FORMAT_R16G16B16_UNORM,
777 VK_FORMAT_R16G16B16_SNORM,
778 VK_FORMAT_R16G16B16_USCALED,
779 VK_FORMAT_R16G16B16_SSCALED,
780 VK_FORMAT_R16G16B16_UINT,
781 VK_FORMAT_R16G16B16_SINT,
782 VK_FORMAT_R16G16B16_SFLOAT,
783 VK_FORMAT_R16G16B16A16_UNORM,
784 VK_FORMAT_R16G16B16A16_SNORM,
785 VK_FORMAT_R16G16B16A16_USCALED,
786 VK_FORMAT_R16G16B16A16_SSCALED,
787 VK_FORMAT_R16G16B16A16_UINT,
788 VK_FORMAT_R16G16B16A16_SINT,
789 VK_FORMAT_R16G16B16A16_SFLOAT,
790 VK_FORMAT_R32_UINT,
791 VK_FORMAT_R32_SINT,
792 VK_FORMAT_R32_SFLOAT,
793 VK_FORMAT_R32G32_UINT,
794 VK_FORMAT_R32G32_SINT,
795 VK_FORMAT_R32G32_SFLOAT,
796 VK_FORMAT_R32G32B32_UINT,
797 VK_FORMAT_R32G32B32_SINT,
798 VK_FORMAT_R32G32B32_SFLOAT,
799 VK_FORMAT_R32G32B32A32_UINT,
800 VK_FORMAT_R32G32B32A32_SINT,
801 VK_FORMAT_R32G32B32A32_SFLOAT,
802 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
803 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
804 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
805 VK_FORMAT_B5G5R5A1_UNORM_PACK16,
806 VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
807 VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
808 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
809
810 // Compressed formats
811 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
812 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
813 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
814 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
815 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
816 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
817 VK_FORMAT_EAC_R11_UNORM_BLOCK,
818 VK_FORMAT_EAC_R11_SNORM_BLOCK,
819 VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
820 VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
821 VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
822 VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
823 VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
824 VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
825 VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
826 VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
827 VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
828 VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
829 VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
830 VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
831 VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
832 VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
833 VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
834 VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
835 VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
836 VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
837 VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
838 VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
839 VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
840 VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
841 VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
842 VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
843 VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
844 VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
845 VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
846 VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
847 VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
848 VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
849 VK_FORMAT_BC5_UNORM_BLOCK,
850 VK_FORMAT_BC5_SNORM_BLOCK,
851 };
852
853 de::MovePtr<tcu::TestCaseGroup> imageTests (new tcu::TestCaseGroup(testCtx, "image_view"));
854 de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type"));
855
856 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
857 {
858 const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type;
859 de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
860 // Uses samplable formats
861 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format"));
862
863 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
864 {
865 const VkFormat format = formats[formatNdx];
866
867 if (isCompressedFormat(format))
868 {
869 // Do not use compressed formats with 1D and 1D array textures.
870 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
871 break;
872 }
873
874 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
875 getFormatCaseName(format).c_str(),
876 (std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
877
878 de::MovePtr<tcu::TestCaseGroup> subresourceRangeTests = createSubresourceRangeTests(testCtx, pipelineConstructionType, viewType, format);
879 de::MovePtr<tcu::TestCaseGroup> componentSwizzleTests = createComponentSwizzleTests(testCtx, pipelineConstructionType, viewType, format);
880
881 formatGroup->addChild(componentSwizzleTests.release());
882 formatGroup->addChild(subresourceRangeTests.release());
883 formatTests->addChild(formatGroup.release());
884 }
885
886 viewTypeGroup->addChild(formatTests.release());
887 viewTypeTests->addChild(viewTypeGroup.release());
888 }
889
890 imageTests->addChild(viewTypeTests.release());
891
892 return imageTests.release();
893 }
894
895 } // pipeline
896 } // vkt
897