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