1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Sampler Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineSamplerTests.hpp"
26 #include "vktPipelineImageSamplingInstance.hpp"
27 #include "vktPipelineSamplerBorderSwizzleTests.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktTestCase.hpp"
31
32 #include "vkImageUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkImageWithMemory.hpp"
41 #include "vkBufferWithMemory.hpp"
42
43 #include "tcuPlatform.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuMaybe.hpp"
47
48 #include "deStringUtil.hpp"
49 #include "deMemory.h"
50
51 #include <iomanip>
52 #include <sstream>
53 #include <vector>
54 #include <string>
55 #include <memory>
56 #include <utility>
57 #include <algorithm>
58
59 namespace vkt
60 {
61 namespace pipeline
62 {
63
64 using namespace vk;
65 using de::MovePtr;
66
67 namespace
68 {
69
70 class SamplerViewType
71 {
72 public:
SamplerViewType(vk::VkImageViewType type,bool normalized=true)73 SamplerViewType (vk::VkImageViewType type, bool normalized = true)
74 : m_viewType(type), m_normalized(normalized)
75 {
76 if (!normalized)
77 DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
78 }
79
operator vk::VkImageViewType() const80 operator vk::VkImageViewType () const
81 {
82 return m_viewType;
83 }
84
isNormalized() const85 bool isNormalized () const
86 {
87 return m_normalized;
88 }
89
90 private:
91 vk::VkImageViewType m_viewType;
92 bool m_normalized;
93 };
94
95 class SamplerTest : public vkt::TestCase
96 {
97 public:
98 SamplerTest (tcu::TestContext& testContext,
99 const char* name,
100 const char* description,
101 SamplerViewType imageViewType,
102 VkFormat imageFormat,
103 int imageSize,
104 float samplerLod,
105 bool separateStencilUsage);
~SamplerTest(void)106 virtual ~SamplerTest (void) {}
107
108 virtual ImageSamplingInstanceParams getImageSamplingInstanceParams (SamplerViewType imageViewType,
109 VkFormat imageFormat,
110 int imageSize,
111 float samplerLod,
112 bool separateStencilUsage) const;
113
114 tcu::Vec4 swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const;
115 virtual void initPrograms (SourceCollections& sourceCollections) const;
116 virtual void checkSupport (Context& context) const;
117 virtual TestInstance* createInstance (Context& context) const;
118 virtual tcu::UVec2 getRenderSize (SamplerViewType viewType) const;
119 virtual std::vector<Vertex4Tex4> createVertices (void) const;
120 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
121 virtual VkComponentMapping getComponentMapping (void) const;
122
123 static std::string getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type);
124 static tcu::IVec3 getImageSize (SamplerViewType viewType, int size);
125 static int getArraySize (SamplerViewType viewType);
126
127 protected:
128 SamplerViewType m_imageViewType;
129 VkFormat m_imageFormat;
130 int m_imageSize;
131 float m_samplerLod;
132 bool m_separateStencilUsage;
133 };
134
135 class SamplerMagFilterTest : public SamplerTest
136 {
137 public:
138 SamplerMagFilterTest (tcu::TestContext& testContext,
139 const char* name,
140 const char* description,
141 SamplerViewType imageViewType,
142 VkFormat imageFormat,
143 VkFilter magFilter,
144 bool separateStencilUsage);
~SamplerMagFilterTest(void)145 virtual ~SamplerMagFilterTest (void) {}
146 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
147
148 private:
149 VkFilter m_magFilter;
150 };
151
152 class SamplerMinFilterTest : public SamplerTest
153 {
154 public:
155 SamplerMinFilterTest (tcu::TestContext& testContext,
156 const char* name,
157 const char* description,
158 SamplerViewType imageViewType,
159 VkFormat imageFormat,
160 VkFilter minFilter,
161 bool separateStencilUsage);
~SamplerMinFilterTest(void)162 virtual ~SamplerMinFilterTest (void) {}
163 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
164
165 private:
166 VkFilter m_minFilter;
167 };
168
169 class SamplerMagReduceFilterTest : public SamplerMagFilterTest
170 {
171 public:
172 SamplerMagReduceFilterTest (tcu::TestContext& testContext,
173 const char* name,
174 const char* description,
175 SamplerViewType imageViewType,
176 VkFormat imageFormat,
177 VkComponentMapping componentMapping,
178 VkSamplerReductionMode reductionMode,
179 bool separateStencilUsage);
180
~SamplerMagReduceFilterTest(void)181 virtual ~SamplerMagReduceFilterTest (void) {}
182 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
183 virtual VkComponentMapping getComponentMapping (void) const;
184
185 private:
186 const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
187 VkComponentMapping m_componentMapping;
188 };
189
190 class SamplerMinReduceFilterTest : public SamplerMinFilterTest
191 {
192 public:
193 SamplerMinReduceFilterTest (tcu::TestContext& testContext,
194 const char* name,
195 const char* description,
196 SamplerViewType imageViewType,
197 VkFormat imageFormat,
198 VkComponentMapping componentMapping,
199 VkSamplerReductionMode reductionMode,
200 bool separateStencilUsage);
201
~SamplerMinReduceFilterTest(void)202 virtual ~SamplerMinReduceFilterTest (void) {}
203 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
204 virtual VkComponentMapping getComponentMapping (void) const;
205
206 private:
207 const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
208 VkComponentMapping m_componentMapping;
209 };
210
211 class SamplerLodTest : public SamplerTest
212 {
213 public:
214 SamplerLodTest (tcu::TestContext& testContext,
215 const char* name,
216 const char* description,
217 SamplerViewType imageViewType,
218 VkFormat imageFormat,
219 VkSamplerMipmapMode mipmapMode,
220 float minLod,
221 float maxLod,
222 float mipLodBias,
223 float samplerLod,
224 bool separateStencilUsage);
~SamplerLodTest(void)225 virtual ~SamplerLodTest (void) {}
226 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
227 virtual void checkSupport (Context& context) const;
228
229 private:
230 VkSamplerMipmapMode m_mipmapMode;
231 float m_minLod;
232 float m_maxLod;
233 float m_mipLodBias;
234 };
235
checkSupport(Context & context) const236 void SamplerLodTest::checkSupport (Context& context) const
237 {
238 SamplerTest::checkSupport(context);
239
240 if (m_mipLodBias != 0.0f && context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
241 !context.getPortabilitySubsetFeatures().samplerMipLodBias)
242 {
243 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Sampler mipmap LOD bias is not supported by this implementation");
244 }
245 }
246
247 class SamplerAddressModesTest : public SamplerTest
248 {
249 public:
250 SamplerAddressModesTest (tcu::TestContext& testContext,
251 const char* name,
252 const char* description,
253 SamplerViewType imageViewType,
254 VkFormat imageFormat,
255 VkSamplerAddressMode addressU,
256 VkSamplerAddressMode addressV,
257 VkSamplerAddressMode addressW,
258 VkBorderColor borderColor,
259 rr::GenericVec4 customBorderColorValue,
260 bool customBorderColorFormatless,
261 bool separateStencilUsage);
~SamplerAddressModesTest(void)262 virtual ~SamplerAddressModesTest (void) {}
263 virtual tcu::UVec2 getRenderSize (SamplerViewType viewType) const;
264 virtual std::vector<Vertex4Tex4> createVertices (void) const;
265 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
266
267 VkSamplerCustomBorderColorCreateInfoEXT getSamplerCustomBorderColorCreateInfo (VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const;
268
269 private:
270 VkSamplerAddressMode m_addressU;
271 VkSamplerAddressMode m_addressV;
272 VkSamplerAddressMode m_addressW;
273 VkBorderColor m_borderColor;
274
275 const VkSamplerCustomBorderColorCreateInfoEXT m_customBorderColorCreateInfo;
276 };
277
278
279 // SamplerTest
280
SamplerTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,float samplerLod,bool separateStencilUsage)281 SamplerTest::SamplerTest (tcu::TestContext& testContext,
282 const char* name,
283 const char* description,
284 SamplerViewType imageViewType,
285 VkFormat imageFormat,
286 int imageSize,
287 float samplerLod,
288 bool separateStencilUsage)
289 : vkt::TestCase (testContext, name, description)
290 , m_imageViewType (imageViewType)
291 , m_imageFormat (imageFormat)
292 , m_imageSize (imageSize)
293 , m_samplerLod (samplerLod)
294 , m_separateStencilUsage (separateStencilUsage)
295 {
296 }
297
getImageSamplingInstanceParams(SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,float samplerLod,bool separateStencilUsage) const298 ImageSamplingInstanceParams SamplerTest::getImageSamplingInstanceParams (SamplerViewType imageViewType,
299 VkFormat imageFormat,
300 int imageSize,
301 float samplerLod,
302 bool separateStencilUsage) const
303 {
304 const tcu::UVec2 renderSize = getRenderSize(imageViewType);
305 const std::vector<Vertex4Tex4> vertices = createVertices();
306 const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo();
307 const VkComponentMapping componentMapping = getComponentMapping();
308
309 const VkImageAspectFlags imageAspect = (!isCompressedFormat(imageFormat) && hasDepthComponent(mapVkFormat(imageFormat).order)) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
310 const deUint32 mipLevels = (imageViewType.isNormalized() ? static_cast<deUint32>(deLog2Floor32(imageSize)) + 1u : 1u);
311
312 const VkImageSubresourceRange subresourceRange =
313 {
314 imageAspect, // VkImageAspectFlags aspectMask;
315 0u, // deUint32 baseMipLevel;
316 mipLevels, // deUint32 mipLevels;
317 0u, // deUint32 baseArrayLayer;
318 (deUint32)SamplerTest::getArraySize(imageViewType) // deUint32 arraySize;
319 };
320
321 return ImageSamplingInstanceParams(renderSize, imageViewType, imageFormat,
322 getImageSize(imageViewType, imageSize),
323 getArraySize(imageViewType),
324 componentMapping, subresourceRange,
325 samplerParams, samplerLod, vertices, separateStencilUsage);
326 }
327
checkSupport(Context & context) const328 void SamplerTest::checkSupport (Context& context) const
329 {
330 checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage));
331 }
332
swizzle(tcu::Vec4 inputData,VkComponentMapping componentMapping,float zeroOrOneValue) const333 tcu::Vec4 SamplerTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const
334 {
335 // Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
336 const vk::VkComponentMapping nonIdentityMapping =
337 {
338 componentMapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : componentMapping.r,
339 componentMapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : componentMapping.g,
340 componentMapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : componentMapping.b,
341 componentMapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : componentMapping.a
342
343 };
344 // array map with enum VkComponentSwizzle
345 const float channelValues[] =
346 {
347 -1.0f, // impossible
348 zeroOrOneValue, // SWIZZLE_0
349 zeroOrOneValue, // SWIZZLE_1
350 inputData.x(),
351 inputData.y(),
352 inputData.z(),
353 inputData.w(),
354 -1.0f
355 };
356
357 return tcu::Vec4(channelValues[nonIdentityMapping.r],
358 channelValues[nonIdentityMapping.g],
359 channelValues[nonIdentityMapping.b],
360 channelValues[nonIdentityMapping.a]);
361 }
362
initPrograms(SourceCollections & sourceCollections) const363 void SamplerTest::initPrograms (SourceCollections& sourceCollections) const
364 {
365 std::ostringstream vertexSrc;
366 std::ostringstream fragmentSrc;
367 const char* texCoordSwizzle = DE_NULL;
368 tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
369 : mapVkFormat(m_imageFormat);
370 tcu::Vec4 lookupScale;
371 tcu::Vec4 lookupBias;
372
373 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
374
375 tcu::Vec4 swizzledScale = swizzle(lookupScale, getComponentMapping(), 1.0f);
376 tcu::Vec4 swizzledBias = swizzle(lookupBias, getComponentMapping(), 0.0f);
377
378 switch (m_imageViewType)
379 {
380 case VK_IMAGE_VIEW_TYPE_1D:
381 texCoordSwizzle = "x";
382 break;
383 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
384 case VK_IMAGE_VIEW_TYPE_2D:
385 texCoordSwizzle = "xy";
386 break;
387 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
388 case VK_IMAGE_VIEW_TYPE_3D:
389 case VK_IMAGE_VIEW_TYPE_CUBE:
390 texCoordSwizzle = "xyz";
391 break;
392 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
393 texCoordSwizzle = "xyzw";
394 break;
395 default:
396 DE_ASSERT(false);
397 break;
398 }
399
400 vertexSrc << "#version 440\n"
401 << "layout(location = 0) in vec4 position;\n"
402 << "layout(location = 1) in vec4 texCoords;\n"
403 << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
404 << "out gl_PerVertex {\n"
405 << " vec4 gl_Position;\n"
406 << "};\n"
407 << "void main (void)\n"
408 << "{\n"
409 << " gl_Position = position;\n"
410 << " vtxTexCoords = texCoords;\n"
411 << "}\n";
412
413 fragmentSrc << "#version 440\n"
414 << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
415 << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
416 << "layout(location = 0) out highp vec4 fragColor;\n"
417 << "void main (void)\n"
418 << "{\n"
419 << " fragColor = ";
420
421 if (m_samplerLod > 0.0f || !m_imageViewType.isNormalized())
422 {
423 DE_ASSERT(m_imageViewType.isNormalized() || (m_samplerLod == 0.0f && !m_imageViewType.isNormalized()));
424 fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
425 }
426 else
427 {
428 fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
429 }
430
431 fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
432 << "}\n";
433
434 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
435 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
436 }
437
createInstance(Context & context) const438 TestInstance* SamplerTest::createInstance (Context& context) const
439 {
440 return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage));
441 }
442
getRenderSize(SamplerViewType viewType) const443 tcu::UVec2 SamplerTest::getRenderSize (SamplerViewType viewType) const
444 {
445 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
446 {
447 return tcu::UVec2(16u, 16u);
448 }
449 else
450 {
451 return tcu::UVec2(16u * 3u, 16u * 2u);
452 }
453 }
454
createVertices(void) const455 std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const
456 {
457 std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
458 // Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries.
459 // TODO: Would be nice to base this on number of texels and subtexel precision. But this
460 // seems to work.
461 for (unsigned int i = 0; i < vertices.size(); ++i) {
462 vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f);
463 if (!m_imageViewType.isNormalized()) {
464 const float imageSize = static_cast<float>(m_imageSize);
465 for (int j = 0; j < tcu::Vec4::SIZE; ++j)
466 vertices[i].texCoord[j] *= imageSize;
467 }
468 }
469 return vertices;
470 }
471
getSamplerCreateInfo(void) const472 VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const
473 {
474 const VkSamplerCreateInfo defaultSamplerParams =
475 {
476 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
477 DE_NULL, // const void* pNext;
478 0u, // VkSamplerCreateFlags flags;
479 VK_FILTER_NEAREST, // VkFilter magFilter;
480 VK_FILTER_NEAREST, // VkFilter minFilter;
481 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
482 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
483 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
484 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
485 0.0f, // float mipLodBias;
486 VK_FALSE, // VkBool32 anisotropyEnable;
487 1.0f, // float maxAnisotropy;
488 false, // VkBool32 compareEnable;
489 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
490 0.0f, // float minLod;
491 (m_imageViewType.isNormalized() ? 0.25f : 0.0f), // float maxLod;
492 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor;
493 !m_imageViewType.isNormalized(), // VkBool32 unnormalizedCoordinates;
494 };
495
496 return defaultSamplerParams;
497 }
498
getComponentMapping(void) const499 VkComponentMapping SamplerTest::getComponentMapping (void) const
500 {
501 const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
502 return componentMapping;
503 }
504
getGlslSamplerType(const tcu::TextureFormat & format,SamplerViewType type)505 std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type)
506 {
507 std::ostringstream samplerType;
508
509 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
510 samplerType << "u";
511 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
512 samplerType << "i";
513
514 switch (type)
515 {
516 case VK_IMAGE_VIEW_TYPE_1D:
517 samplerType << "sampler1D";
518 break;
519
520 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
521 samplerType << "sampler1DArray";
522 break;
523
524 case VK_IMAGE_VIEW_TYPE_2D:
525 samplerType << "sampler2D";
526 break;
527
528 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
529 samplerType << "sampler2DArray";
530 break;
531
532 case VK_IMAGE_VIEW_TYPE_3D:
533 samplerType << "sampler3D";
534 break;
535
536 case VK_IMAGE_VIEW_TYPE_CUBE:
537 samplerType << "samplerCube";
538 break;
539
540 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
541 samplerType << "samplerCubeArray";
542 break;
543
544 default:
545 DE_FATAL("Unknown image view type");
546 break;
547 }
548
549 return samplerType.str();
550 }
551
getImageSize(SamplerViewType viewType,int size)552 tcu::IVec3 SamplerTest::getImageSize (SamplerViewType viewType, int size)
553 {
554 switch (viewType)
555 {
556 case VK_IMAGE_VIEW_TYPE_1D:
557 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
558 return tcu::IVec3(size, 1, 1);
559
560 case VK_IMAGE_VIEW_TYPE_3D:
561 return tcu::IVec3(size, size, 4);
562
563 default:
564 break;
565 }
566
567 return tcu::IVec3(size, size, 1);
568 }
569
getArraySize(SamplerViewType viewType)570 int SamplerTest::getArraySize (SamplerViewType viewType)
571 {
572 switch (viewType)
573 {
574 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
575 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
576 case VK_IMAGE_VIEW_TYPE_CUBE:
577 return 6;
578
579 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
580 return 36;
581
582 default:
583 break;
584 }
585
586 return 1;
587 }
588
589
590 // SamplerMagFilterTest
591
SamplerMagFilterTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,VkFilter magFilter,bool separateStencilUsage)592 SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext& testContext,
593 const char* name,
594 const char* description,
595 SamplerViewType imageViewType,
596 VkFormat imageFormat,
597 VkFilter magFilter,
598 bool separateStencilUsage)
599 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage)
600 , m_magFilter (magFilter)
601 {
602 }
603
getSamplerCreateInfo(void) const604 VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const
605 {
606 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
607 samplerParams.magFilter = m_magFilter;
608
609 return samplerParams;
610 }
611
612
613 // SamplerMinFilterTest
614
SamplerMinFilterTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,VkFilter minFilter,bool separateStencilUsage)615 SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext& testContext,
616 const char* name,
617 const char* description,
618 SamplerViewType imageViewType,
619 VkFormat imageFormat,
620 VkFilter minFilter,
621 bool separateStencilUsage)
622 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, 0.0f, separateStencilUsage)
623 , m_minFilter (minFilter)
624 {
625 }
626
getSamplerCreateInfo(void) const627 VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const
628 {
629 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
630 samplerParams.minFilter = m_minFilter;
631 // set minLod to epsilon, to force use of the minFilter
632 samplerParams.minLod = 0.01f;
633
634 return samplerParams;
635 }
636
637
638 namespace
639 {
640
getSamplerReductionCreateInfo(VkSamplerReductionMode reductionMode)641 VkSamplerReductionModeCreateInfo getSamplerReductionCreateInfo (VkSamplerReductionMode reductionMode)
642 {
643 const VkSamplerReductionModeCreateInfo ret =
644 {
645 VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, // VkStructureType sType
646 DE_NULL, // const void* pNext
647 reductionMode // VkSamplerReductionMode reductionMode
648 };
649 return ret;
650 }
651
652 }
653
654
655 // SamplerMagReduceFilterTest
656
SamplerMagReduceFilterTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,VkComponentMapping componentMapping,VkSamplerReductionMode reductionMode,bool separateStencilUsage)657 SamplerMagReduceFilterTest::SamplerMagReduceFilterTest (tcu::TestContext& testContext,
658 const char* name,
659 const char* description,
660 SamplerViewType imageViewType,
661 VkFormat imageFormat,
662 VkComponentMapping componentMapping,
663 VkSamplerReductionMode reductionMode,
664 bool separateStencilUsage)
665 : SamplerMagFilterTest (testContext, name, description, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
666 , m_reductionCreaterInfo (getSamplerReductionCreateInfo(reductionMode))
667 , m_componentMapping (componentMapping)
668 {
669 }
670
getSamplerCreateInfo(void) const671 VkSamplerCreateInfo SamplerMagReduceFilterTest::getSamplerCreateInfo (void) const
672 {
673 VkSamplerCreateInfo samplerParams = SamplerMagFilterTest::getSamplerCreateInfo();
674
675 samplerParams.pNext = &m_reductionCreaterInfo;
676
677 return samplerParams;
678 }
679
getComponentMapping(void) const680 VkComponentMapping SamplerMagReduceFilterTest::getComponentMapping (void) const
681 {
682 return m_componentMapping;
683 }
684
685 // SamplerMinReduceFilterTest
686
SamplerMinReduceFilterTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,VkComponentMapping componentMapping,VkSamplerReductionMode reductionMode,bool separateStencilUsage)687 SamplerMinReduceFilterTest::SamplerMinReduceFilterTest (tcu::TestContext& testContext,
688 const char* name,
689 const char* description,
690 SamplerViewType imageViewType,
691 VkFormat imageFormat,
692 VkComponentMapping componentMapping,
693 VkSamplerReductionMode reductionMode,
694 bool separateStencilUsage)
695 : SamplerMinFilterTest (testContext, name, description, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
696 , m_reductionCreaterInfo (getSamplerReductionCreateInfo(reductionMode))
697 , m_componentMapping (componentMapping)
698 {
699 }
700
getSamplerCreateInfo(void) const701 VkSamplerCreateInfo SamplerMinReduceFilterTest::getSamplerCreateInfo (void) const
702 {
703 VkSamplerCreateInfo samplerParams = SamplerMinFilterTest::getSamplerCreateInfo();
704
705 samplerParams.pNext = &m_reductionCreaterInfo;
706
707 return samplerParams;
708 }
709
getComponentMapping(void) const710 VkComponentMapping SamplerMinReduceFilterTest::getComponentMapping (void) const
711 {
712 return m_componentMapping;
713 }
714
715 // SamplerLodTest
716
SamplerLodTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerMipmapMode mipmapMode,float minLod,float maxLod,float mipLodBias,float samplerLod,bool separateStencilUsage)717 SamplerLodTest::SamplerLodTest (tcu::TestContext& testContext,
718 const char* name,
719 const char* description,
720 SamplerViewType imageViewType,
721 VkFormat imageFormat,
722 VkSamplerMipmapMode mipmapMode,
723 float minLod,
724 float maxLod,
725 float mipLodBias,
726 float samplerLod,
727 bool separateStencilUsage)
728 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, samplerLod, separateStencilUsage)
729 , m_mipmapMode (mipmapMode)
730 , m_minLod (minLod)
731 , m_maxLod (maxLod)
732 , m_mipLodBias (mipLodBias)
733 {
734 }
735
getSamplerCreateInfo(void) const736 VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const
737 {
738 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
739
740 samplerParams.mipmapMode = m_mipmapMode;
741 samplerParams.minLod = m_minLod;
742 samplerParams.maxLod = m_maxLod;
743 samplerParams.mipLodBias = m_mipLodBias;
744
745 return samplerParams;
746 }
747
748
749 // SamplerAddressModesTest
750
SamplerAddressModesTest(tcu::TestContext & testContext,const char * name,const char * description,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerAddressMode addressU,VkSamplerAddressMode addressV,VkSamplerAddressMode addressW,VkBorderColor borderColor,rr::GenericVec4 customBorderColorValue,bool customBorderColorFormatless,bool separateStencilUsage)751 SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext& testContext,
752 const char* name,
753 const char* description,
754 SamplerViewType imageViewType,
755 VkFormat imageFormat,
756 VkSamplerAddressMode addressU,
757 VkSamplerAddressMode addressV,
758 VkSamplerAddressMode addressW,
759 VkBorderColor borderColor,
760 rr::GenericVec4 customBorderColorValue,
761 bool customBorderColorFormatless,
762 bool separateStencilUsage)
763 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage)
764 , m_addressU (addressU)
765 , m_addressV (addressV)
766 , m_addressW (addressW)
767 , m_borderColor (borderColor)
768 , m_customBorderColorCreateInfo (getSamplerCustomBorderColorCreateInfo(imageFormat, customBorderColorValue, customBorderColorFormatless))
769 {
770 }
771
getRenderSize(SamplerViewType viewType) const772 tcu::UVec2 SamplerAddressModesTest::getRenderSize (SamplerViewType viewType) const
773 {
774 return 4u * SamplerTest::getRenderSize(viewType);
775 }
776
createVertices(void) const777 std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const
778 {
779 std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
780
781 switch (m_imageViewType)
782 {
783 case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
784 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
785 vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
786
787 break;
788
789 case VK_IMAGE_VIEW_TYPE_2D:
790 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
791 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
792 vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
793
794 break;
795
796 case VK_IMAGE_VIEW_TYPE_3D:
797 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
798 vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
799
800 break;
801
802 case VK_IMAGE_VIEW_TYPE_CUBE:
803 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
804 break;
805
806 default:
807 DE_ASSERT(false);
808 }
809
810 return vertices;
811 }
812
getSamplerCreateInfo(void) const813 VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const
814 {
815 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
816 samplerParams.addressModeU = m_addressU;
817 samplerParams.addressModeV = m_addressV;
818 samplerParams.addressModeW = m_addressW;
819 samplerParams.borderColor = m_borderColor;
820
821 if (m_borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
822 m_borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT)
823 {
824 samplerParams.pNext = &m_customBorderColorCreateInfo;
825 }
826
827 return samplerParams;
828 }
829
getSamplerCustomBorderColorCreateInfo(VkFormat format,rr::GenericVec4 customBorderColorValue,bool customBorderColorFormatless) const830 VkSamplerCustomBorderColorCreateInfoEXT SamplerAddressModesTest::getSamplerCustomBorderColorCreateInfo (VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const
831 {
832 const VkSamplerCustomBorderColorCreateInfoEXT defaultSamplerCustomBorderColorParams =
833 {
834 VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
835 DE_NULL,
836 mapVkColor(customBorderColorValue),
837 customBorderColorFormatless ? VK_FORMAT_UNDEFINED : format
838 };
839
840 return defaultSamplerCustomBorderColorParams;
841 }
842
843
844 // Utilities to create test nodes
845
getFormatCaseName(const VkFormat format)846 std::string getFormatCaseName (const VkFormat format)
847 {
848 const std::string fullName = getFormatName(format);
849
850 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
851
852 return de::toLower(fullName.substr(10));
853 }
854
createSamplerMagFilterTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)855 MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
856 {
857 MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter"));
858
859 if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
860 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
861 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
862
863 return samplerMagFilterTests;
864 }
865
createSamplerMinFilterTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)866 MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
867 {
868 MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter"));
869
870 if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
871 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
872 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
873
874 return samplerMinFilterTests;
875 }
876
877 const VkComponentMapping reduceFilterComponentMappings[] =
878 {
879 // filterMinmaxImageComponentMapping == false - compatible mappings:
880 { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO },
881 { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO },
882
883 // other mappings
884 { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A },
885 { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A },
886 { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R },
887 };
888
getShortComponentSwizzleName(VkComponentSwizzle componentSwizzle)889 static std::string getShortComponentSwizzleName (VkComponentSwizzle componentSwizzle)
890 {
891 const std::string fullName = getComponentSwizzleName(componentSwizzle);
892 const char* prefix = "VK_COMPONENT_SWIZZLE_";
893
894 DE_ASSERT(de::beginsWith(fullName, prefix));
895
896 return de::toLower(fullName.substr(deStrnlen(prefix, -1)));
897 }
898
getComponentMappingGroupName(const VkComponentMapping & componentMapping)899 static std::string getComponentMappingGroupName (const VkComponentMapping& componentMapping)
900 {
901 std::ostringstream name;
902
903 name << "comp_";
904
905 name << getShortComponentSwizzleName(componentMapping.r) << "_"
906 << getShortComponentSwizzleName(componentMapping.g) << "_"
907 << getShortComponentSwizzleName(componentMapping.b) << "_"
908 << getShortComponentSwizzleName(componentMapping.a);
909
910 return name.str();
911 }
912
createSamplerMagReduceFilterTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)913 MovePtr<tcu::TestCaseGroup> createSamplerMagReduceFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
914 {
915 MovePtr<tcu::TestCaseGroup> samplerMagReduceFilterTests (new tcu::TestCaseGroup(testCtx, "mag_reduce", "Tests for magnification reduce filter"));
916
917 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
918 {
919 const VkComponentMapping& mapping = reduceFilterComponentMappings[i];
920
921 MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
922
923 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
924 {
925 componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "average", "Magnifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, separateStencilUsage));
926 }
927 componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "min", "Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN_EXT, separateStencilUsage));
928 componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "max", "Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX_EXT, separateStencilUsage));
929 samplerMagReduceFilterTests->addChild(componentGroup.release());
930 }
931 return samplerMagReduceFilterTests;
932 }
933
createSamplerMinReduceFilterTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)934 MovePtr<tcu::TestCaseGroup> createSamplerMinReduceFilterTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
935 {
936 MovePtr<tcu::TestCaseGroup> samplerMinReduceFilterTests (new tcu::TestCaseGroup(testCtx, "min_reduce", "Tests for minification reduce filter"));
937
938 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
939 {
940 const VkComponentMapping& mapping = reduceFilterComponentMappings[i];
941
942 MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
943
944 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
945 {
946 componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "average", "Minifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, separateStencilUsage));
947 }
948 componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "min", "Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN_EXT, separateStencilUsage));
949 componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "max", "Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX_EXT", imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX_EXT, separateStencilUsage));
950 samplerMinReduceFilterTests->addChild(componentGroup.release());
951 }
952 return samplerMinReduceFilterTests;
953 }
954
createSamplerLodTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerMipmapMode mipmapMode,bool separateStencilUsage)955 MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, bool separateStencilUsage)
956 {
957 struct TestCaseConfig
958 {
959 const char* name;
960 const char* description;
961 float minLod;
962 float maxLod;
963 float mipLodBias;
964 float lod;
965 };
966
967 TestCaseConfig testCaseConfigs [] =
968 {
969 { "equal_min_3_max_3", "minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0", 3.0f, 3.0f, 0.0f, 0.0f },
970 { "select_min_1", "minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0", 1.0f, 5.0f, 0.0f, 0.0f },
971 { "select_max_4", "minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5", 0.0f, 4.0f, 0.0f, 5.0f },
972 { "select_bias_2_1", "minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0", 0.0f, 2.1f, 5.0f, 0.0f },
973 { "select_bias_2_5", "minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0", 0.0f, 5.0f, 2.5f, 0.00001f },
974 { "select_bias_3_1", "minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0", 0.0f, 5.0f, -0.9f, 4.0f },
975 { "select_bias_3_7", "minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7", 0.0f, 5.0f, 3.0f, 0.7f },
976 };
977
978 MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD"));
979
980 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
981 {
982 const TestCaseConfig& config = testCaseConfigs[configNdx];
983
984 samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod, separateStencilUsage));
985 }
986
987 return samplerLodTests;
988 }
989
createSamplerMipmapTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)990 MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
991 {
992 MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes"));
993
994 // Mipmap mode: nearest
995 MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST"));
996 mipmapNearestTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST, separateStencilUsage).release());
997 samplerMipmapTests->addChild(mipmapNearestTests.release());
998
999 // Mipmap mode: linear
1000 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
1001 {
1002 MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR"));
1003 mipmapLinearTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR, separateStencilUsage).release());
1004 samplerMipmapTests->addChild(mipmapLinearTests.release());
1005 }
1006
1007 return samplerMipmapTests;
1008 }
1009
getAddressModesCaseName(VkSamplerAddressMode u,VkSamplerAddressMode v,VkSamplerAddressMode w,BorderColor border,tcu::IVec4 customIntValue,bool formatless)1010 std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border, tcu::IVec4 customIntValue, bool formatless)
1011 {
1012 static const char* borderColorNames[BORDER_COLOR_COUNT] =
1013 {
1014 "opaque_black",
1015 "opaque_white",
1016 "transparent_black",
1017 "custom"
1018 };
1019
1020 std::ostringstream caseName;
1021
1022 if (u == v && v == w)
1023 {
1024 const std::string fullName = getSamplerAddressModeName(u);
1025 DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
1026
1027 caseName << "all_";
1028 caseName << de::toLower(fullName.substr(19));
1029
1030 if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
1031 {
1032 caseName << "_" << borderColorNames[border];
1033 }
1034 }
1035 else
1036 {
1037 const std::string fullNameU = getSamplerAddressModeName(u);
1038 const std::string fullNameV = getSamplerAddressModeName(v);
1039 const std::string fullNameW = getSamplerAddressModeName(w);
1040
1041 DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
1042 DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
1043 DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
1044
1045 caseName << "uvw"
1046 << "_" << de::toLower(fullNameU.substr(19))
1047 << "_" << de::toLower(fullNameV.substr(19))
1048 << "_" << de::toLower(fullNameW.substr(19));
1049 }
1050
1051 if (border == BORDER_COLOR_CUSTOM)
1052 {
1053 caseName << "_";
1054 for (int i = 0; i < 4; i++)
1055 caseName << customIntValue[i];
1056
1057 if (formatless)
1058 caseName << "_formatless";
1059
1060 }
1061 return caseName.str();
1062 }
1063
createSamplerAddressModesTests(tcu::TestContext & testCtx,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)1064 MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
1065 {
1066 struct TestCaseConfig
1067 {
1068 TestCaseConfig (VkSamplerAddressMode _u,
1069 VkSamplerAddressMode _v,
1070 VkSamplerAddressMode _w,
1071 BorderColor _border,
1072 bool _customColorFormatless = false,
1073 tcu::Vec4 _customColorValueFloat = tcu::Vec4(),
1074 tcu::IVec4 _customColorValueInt = tcu::IVec4())
1075 : u(_u), v(_v), w(_w), border(_border), customColorFormatless(_customColorFormatless)
1076 , customColorValueFloat(_customColorValueFloat), customColorValueInt(_customColorValueInt)
1077 {
1078
1079 }
1080
1081 VkSamplerAddressMode u;
1082 VkSamplerAddressMode v;
1083 VkSamplerAddressMode w;
1084 BorderColor border;
1085 bool customColorFormatless;
1086 tcu::Vec4 customColorValueFloat;
1087 tcu::IVec4 customColorValueInt;
1088 };
1089
1090 const TestCaseConfig testCaseConfigs[] =
1091 {
1092 // All address modes equal
1093 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK },
1094 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
1095 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
1096 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK },
1097
1098 // All address modes equal using border color
1099 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_TRANSPARENT_BLACK },
1100 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_BLACK },
1101 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1102
1103 // Pairwise combinations of address modes not covered by previous tests
1104 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1105 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1106 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1107 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1108 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1109 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1110 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1111 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1112 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1113 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1114 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1115 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1116 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1117 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1118 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1119 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1120 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1121 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1122 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1123 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1124 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1125 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1126
1127 // Custom border color tests
1128 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1129 false, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::IVec4(0, 0, 0, 0) },
1130 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1131 false, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(0, 0, 1, 1) },
1132 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1133 false, tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::IVec4(1, 0, 0, 0) },
1134 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1135 false, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::IVec4(1, 0, 0, 1) },
1136 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1137 false, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(1, 0, 1, 1) },
1138 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1139 false, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::IVec4(1, 1, 0, 1) },
1140
1141 // Custom border color formatless
1142 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1143 true, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(1, 0, 1, 1) },
1144 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1145 true, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::IVec4(1, 1, 0, 1) },
1146 };
1147
1148 MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes"));
1149
1150 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1151 {
1152 const TestCaseConfig& config = testCaseConfigs[configNdx];
1153
1154 if (!imageViewType.isNormalized() &&
1155 ((config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
1156 (config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)))
1157 continue;
1158
1159 // VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16 and VK_FORMAT_B5G5R5A1_UNORM_PACK16 are forbidden
1160 // for non-formatless custom border color.
1161 if ((imageFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1162 imageFormat == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1163 imageFormat == VK_FORMAT_B5G5R5A1_UNORM_PACK16) && config.border == BORDER_COLOR_CUSTOM && config.customColorFormatless)
1164 continue;
1165
1166 samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx,
1167 getAddressModesCaseName(config.u, config.v, config.w, config.border, config.customColorValueInt, config.customColorFormatless).c_str(),
1168 "",
1169 imageViewType,
1170 imageFormat,
1171 config.u, config.v, config.w,
1172 getFormatBorderColor(config.border, imageFormat),
1173 getFormatCustomBorderColor(config.customColorValueFloat, config.customColorValueInt, imageFormat),
1174 config.customColorFormatless,
1175 separateStencilUsage));
1176 }
1177
1178 return samplerAddressModesTests;
1179 }
1180
1181 // Exact sampling case:
1182 // 1) Create a texture and a framebuffer image of the same size.
1183 // 2) Draw a full screen quad with the texture and VK_FILTER_NEAREST.
1184 // 3) Verify the rendered image matches the texture exactly.
1185 class ExactSamplingCase : public vkt::TestCase
1186 {
1187 public:
1188 struct Params
1189 {
1190 vk::VkFormat format;
1191 bool unnormalizedCoordinates;
1192 bool solidColor;
1193 tcu::Maybe<float> offsetSign; // -1.0 or 1.0
1194 };
1195
1196 struct PushConstants
1197 {
1198 float texWidth;
1199 float texHeight;
1200 };
1201
1202 struct VertexData
1203 {
1204 tcu::Vec2 vtxCoords;
1205 tcu::Vec2 texCoords;
1206
1207 static vk::VkVertexInputBindingDescription getBindingDescription (void);
1208 static std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions (void);
1209 };
1210
1211 ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params);
~ExactSamplingCase(void)1212 virtual ~ExactSamplingCase (void) {}
1213
1214 virtual void initPrograms (vk::SourceCollections& programCollection) const;
1215 virtual TestInstance* createInstance (Context& context) const;
1216 virtual void checkSupport (Context& context) const;
1217
1218 private:
1219 Params m_params;
1220 };
1221
1222 class ExactSamplingInstance : public vkt::TestInstance
1223 {
1224 public:
1225 using Params = ExactSamplingCase::Params;
1226
1227 ExactSamplingInstance (Context& context, const Params& params);
~ExactSamplingInstance(void)1228 virtual ~ExactSamplingInstance (void) {}
1229
1230 virtual tcu::TestStatus iterate (void);
1231
1232 vk::VkExtent3D getTextureExtent (void) const;
1233
1234 private:
1235 Params m_params;
1236 };
1237
getBindingDescription(void)1238 vk::VkVertexInputBindingDescription ExactSamplingCase::VertexData::getBindingDescription (void)
1239 {
1240 static const vk::VkVertexInputBindingDescription desc =
1241 {
1242 0u, // deUint32 binding;
1243 static_cast<deUint32>(sizeof(ExactSamplingCase::VertexData)), // deUint32 stride;
1244 vk::VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
1245 };
1246
1247 return desc;
1248 }
1249
getAttributeDescriptions(void)1250 std::vector<vk::VkVertexInputAttributeDescription> ExactSamplingCase::VertexData::getAttributeDescriptions (void)
1251 {
1252 static const std::vector<vk::VkVertexInputAttributeDescription> desc =
1253 {
1254 {
1255 0u, // deUint32 location;
1256 0u, // deUint32 binding;
1257 vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1258 static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, vtxCoords)), // deUint32 offset;
1259 },
1260 {
1261 1u, // deUint32 location;
1262 0u, // deUint32 binding;
1263 vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1264 static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, texCoords)), // deUint32 offset;
1265 },
1266 };
1267
1268 return desc;
1269 }
1270
1271
ExactSamplingCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const Params & params)1272 ExactSamplingCase::ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params)
1273 : vkt::TestCase{testCtx, name, description}, m_params(params)
1274 {
1275 }
1276
initPrograms(vk::SourceCollections & programCollection) const1277 void ExactSamplingCase::initPrograms (vk::SourceCollections& programCollection) const
1278 {
1279 std::ostringstream vertexShader;
1280
1281 std::string texCoordX = "inTexCoord.x";
1282 std::string texCoordY = "inTexCoord.y";
1283
1284 if (m_params.unnormalizedCoordinates)
1285 {
1286 texCoordX += " * pushc.texWidth";
1287 texCoordY += " * pushc.texHeight";
1288 }
1289
1290 vertexShader
1291 << "#version 450\n"
1292 << "\n"
1293 << "layout(push_constant, std430) uniform PushConstants\n"
1294 << "{\n"
1295 << " float texWidth;\n"
1296 << " float texHeight;\n"
1297 << "} pushc;\n"
1298 << "\n"
1299 << "layout(location = 0) in vec2 inPosition;\n"
1300 << "layout(location = 1) in vec2 inTexCoord;\n"
1301 << "\n"
1302 << "layout(location = 0) out vec2 fragTexCoord;\n"
1303 << "\n"
1304 << "void main() {\n"
1305 << " gl_Position = vec4(inPosition, 0.0, 1.0);\n"
1306 << " fragTexCoord = vec2(" << texCoordX << ", " << texCoordY << ");\n"
1307 << "}\n"
1308 ;
1309
1310 programCollection.glslSources.add("vert") << glu::VertexSource{vertexShader.str()};
1311
1312 std::ostringstream fragmentShader;
1313
1314 std::string typePrefix;
1315 if (vk::isIntFormat(m_params.format))
1316 typePrefix = "i";
1317 else if (vk::isUintFormat(m_params.format))
1318 typePrefix = "u";
1319
1320 const std::string samplerType = typePrefix + "sampler2D";
1321 const std::string colorType = typePrefix + "vec4";
1322
1323 fragmentShader
1324 << "#version 450\n"
1325 << "\n"
1326 << "layout(set = 0, binding = 0) uniform " << samplerType << " texSampler;\n"
1327 << "\n"
1328 << "layout(location = 0) in vec2 fragTexCoord;\n"
1329 << "\n"
1330 << "layout(location = 0) out " << colorType << " outColor;\n"
1331 << "\n"
1332 << "void main() {\n";
1333
1334 if (m_params.unnormalizedCoordinates)
1335 {
1336 fragmentShader << " outColor = textureLod(texSampler, fragTexCoord, 0.0f);";
1337 }
1338 else
1339 {
1340 fragmentShader << " outColor = texture(texSampler, fragTexCoord);\n";
1341 }
1342
1343 fragmentShader << "}\n";
1344
1345 programCollection.glslSources.add("frag") << glu::FragmentSource{fragmentShader.str()};
1346 }
1347
createInstance(Context & context) const1348 TestInstance* ExactSamplingCase::createInstance (Context& context) const
1349 {
1350 return new ExactSamplingInstance{context, m_params};
1351 }
1352
checkSupport(Context & context) const1353 void ExactSamplingCase::checkSupport (Context& context) const
1354 {
1355 const auto& vki = context.getInstanceInterface();
1356 const auto physicalDevice = context.getPhysicalDevice();
1357 const auto props = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, m_params.format);
1358 const vk::VkFormatFeatureFlags requiredFeatures =
1359 (vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT
1360 |vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
1361 |vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
1362 |vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
1363 |(m_params.solidColor ? vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT : 0)
1364 );
1365
1366 if ((props.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
1367 TCU_THROW(NotSupportedError, "Selected format does not support the required features");
1368 }
1369
ExactSamplingInstance(Context & context,const Params & params)1370 ExactSamplingInstance::ExactSamplingInstance (Context& context, const Params& params)
1371 : vkt::TestInstance{context}, m_params(params)
1372 {
1373 }
1374
getTextureExtent(void) const1375 vk::VkExtent3D ExactSamplingInstance::getTextureExtent (void) const
1376 {
1377 return vk::makeExtent3D(256u, 256u, 1u);
1378 }
1379
iterate(void)1380 tcu::TestStatus ExactSamplingInstance::iterate (void)
1381 {
1382 const auto& vkd = m_context.getDeviceInterface();
1383 const auto device = m_context.getDevice();
1384 auto& allocator = m_context.getDefaultAllocator();
1385 const auto queue = m_context.getUniversalQueue();
1386 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1387
1388 const auto tcuFormat = vk::mapVkFormat(m_params.format);
1389 const auto formatInfo = tcu::getTextureFormatInfo(tcuFormat);
1390 const auto texExtent = getTextureExtent();
1391 const auto texUsage = (vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT);
1392 const auto fbUsage = (vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
1393 const auto descType = vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1394 const auto texLayout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1395 const bool& unnorm = m_params.unnormalizedCoordinates;
1396
1397 // Some code below depends on this.
1398 DE_ASSERT(texExtent.depth == 1u);
1399
1400 const vk::VkImageCreateInfo texImgCreateInfo =
1401 {
1402 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1403 nullptr, // const void* pNext;
1404 0u, // VkImageCreateFlags flags;
1405 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1406 m_params.format, // VkFormat format;
1407 texExtent, // VkExtent3D extent;
1408 1u, // deUint32 mipLevels;
1409 1u, // deUint32 arrayLayers;
1410 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1411 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1412 texUsage, // VkImageUsageFlags usage;
1413 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1414 1u, // deUint32 queueFamilyIndexCount;
1415 &queueIndex, // const deUint32* pQueueFamilyIndices;
1416 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1417 };
1418
1419 const vk::VkImageCreateInfo fbImgCreateInfo =
1420 {
1421 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1422 nullptr, // const void* pNext;
1423 0u, // VkImageCreateFlags flags;
1424 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1425 m_params.format, // VkFormat format;
1426 texExtent, // VkExtent3D extent;
1427 1u, // deUint32 mipLevels;
1428 1u, // deUint32 arrayLayers;
1429 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1430 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1431 fbUsage, // VkImageUsageFlags usage;
1432 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1433 1u, // deUint32 queueFamilyIndexCount;
1434 &queueIndex, // const deUint32* pQueueFamilyIndices;
1435 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1436 };
1437
1438 // Create main and framebuffer images.
1439 const vk::ImageWithMemory texImage {vkd, device, allocator, texImgCreateInfo, vk::MemoryRequirement::Any};
1440 const vk::ImageWithMemory fbImage {vkd, device, allocator, fbImgCreateInfo, vk::MemoryRequirement::Any};
1441
1442 // Corresponding image views.
1443 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1444 const auto texView = vk::makeImageView(vkd, device, texImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
1445 const auto fbView = vk::makeImageView(vkd, device, fbImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
1446
1447 // Buffers to create the texture and verify results.
1448 const vk::VkDeviceSize texBufferSize = static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * texExtent.width * texExtent.height * texExtent.depth);
1449 const auto texBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1450 const auto resultsBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1451 const vk::BufferWithMemory texBuffer {vkd, device, allocator, texBufferInfo, vk::MemoryRequirement::HostVisible};
1452 const vk::BufferWithMemory resultsBuffer {vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible};
1453
1454 // Create texture.
1455 const tcu::IVec2 iImgSize {static_cast<int>(texExtent.width), static_cast<int>(texExtent.height)};
1456 auto& texBufferAlloc = texBuffer.getAllocation();
1457 auto texBufferPtr = reinterpret_cast<char*>(texBufferAlloc.getHostPtr()) + texBufferAlloc.getOffset();
1458 const tcu::PixelBufferAccess texPixels {tcuFormat, iImgSize[0], iImgSize[1], 1, texBufferPtr};
1459
1460 const int W = texPixels.getWidth();
1461 const int H = texPixels.getHeight();
1462 const int D = texPixels.getDepth();
1463
1464 const float divX = static_cast<float>(W - 1);
1465 const float divY = static_cast<float>(H - 1);
1466
1467 tcu::Vec4 texColor;
1468
1469 for (int x = 0; x < W; ++x)
1470 for (int y = 0; y < H; ++y)
1471 for (int z = 0; z < D; ++z)
1472 {
1473 if (m_params.solidColor)
1474 {
1475 // Texture with solid color for filtered sampling.
1476 texColor = tcu::Vec4{0.5f, 0.25f, 0.7529411764705882f, 1.0f};
1477 }
1478 else
1479 {
1480 // Use a color gradient otherwise.
1481 const float colorX = static_cast<float>(x) / divX;
1482 const float colorY = static_cast<float>(y) / divY;
1483 const float colorZ = std::min(colorX, colorY);
1484
1485 texColor = tcu::Vec4{colorX, colorY, colorZ, 1.0f};
1486 }
1487 const tcu::Vec4 finalColor = (texColor - formatInfo.lookupBias) / formatInfo.lookupScale;
1488 texPixels.setPixel(finalColor, x, y, z);
1489 }
1490
1491 vk::flushAlloc(vkd, device, texBufferAlloc);
1492
1493 float minU = 0.0f;
1494 float maxU = 1.0f;
1495 float minV = 0.0f;
1496 float maxV = 1.0f;
1497
1498 // When testing the edges, apply a texture offset of almost half a texel, so the sample location is very close to the texel border.
1499 if (m_params.offsetSign)
1500 {
1501 const float sign = m_params.offsetSign.get(); DE_ASSERT(sign == 1.0f || sign == -1.0f);
1502 const float offsetWidth = 0.499f / static_cast<float>(texExtent.width);
1503 const float offsetHeight = 0.499f / static_cast<float>(texExtent.height);
1504
1505 minU += sign * offsetWidth;
1506 maxU += sign * offsetWidth;
1507 minV += sign * offsetHeight;
1508 maxV += sign * offsetHeight;
1509 }
1510
1511 const std::vector<ExactSamplingCase::VertexData> fullScreenQuad =
1512 {
1513 {{ 1.f, -1.f }, { maxU, minV }, },
1514 {{ -1.f, -1.f }, { minU, minV }, },
1515 {{ -1.f, 1.f }, { minU, maxV }, },
1516 {{ -1.f, 1.f }, { minU, maxV }, },
1517 {{ 1.f, -1.f }, { maxU, minV }, },
1518 {{ 1.f, 1.f }, { maxU, maxV }, },
1519 };
1520
1521 // Vertex buffer.
1522 const vk::VkDeviceSize vertexBufferSize = static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
1523 const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1524 const vk::BufferWithMemory vertexBuffer {vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible};
1525
1526 // Copy data to vertex buffer.
1527 const auto& vertexAlloc = vertexBuffer.getAllocation();
1528 const auto vertexDataPtr = reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
1529 deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
1530 vk::flushAlloc(vkd, device, vertexAlloc);
1531
1532 // Descriptor set layout.
1533 vk::DescriptorSetLayoutBuilder layoutBuilder;
1534 layoutBuilder.addSingleBinding(descType, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1535 const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1536
1537 // Descriptor pool.
1538 vk::DescriptorPoolBuilder poolBuilder;
1539 poolBuilder.addType(descType);
1540 const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1541
1542 // Descriptor set.
1543 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1544
1545 // Texture sampler. When using a solid color, test linear filtering. Linear filtering may incur in a small precission loss, but
1546 // it should be minimal and we should get the same color when converting back to the original format.
1547 const auto minMagFilter = (m_params.solidColor ? vk::VK_FILTER_LINEAR : vk::VK_FILTER_NEAREST);
1548 const auto addressMode = (unnorm ? vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : vk::VK_SAMPLER_ADDRESS_MODE_REPEAT);
1549 const auto unnormalizedCoordinates = (unnorm ? VK_TRUE : VK_FALSE);
1550
1551 const vk::VkSamplerCreateInfo samplerCreateInfo =
1552 {
1553 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
1554 nullptr, // const void* pNext;
1555 0u, // VkSamplerCreateFlags flags;
1556 minMagFilter, // VkFilter magFilter;
1557 minMagFilter, // VkFilter minFilter;
1558 vk::VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
1559 addressMode, // VkSamplerAddressMode addressModeU;
1560 addressMode, // VkSamplerAddressMode addressModeV;
1561 addressMode, // VkSamplerAddressMode addressModeW;
1562 0.0f, // float mipLodBias;
1563 VK_FALSE, // VkBool32 anisotropyEnable;
1564 1.0f, // float maxAnisotropy;
1565 VK_FALSE, // VkBool32 compareEnable;
1566 vk::VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1567 0.0f, // float minLod;
1568 0.0f, // float maxLod;
1569 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
1570 unnormalizedCoordinates, // VkBool32 unnormalizedCoordinates;
1571 };
1572 const auto texSampler = vk::createSampler(vkd, device, &samplerCreateInfo);
1573
1574 // Update descriptor set with the descriptor.
1575 vk::DescriptorSetUpdateBuilder updateBuilder;
1576 const auto descriptorImageInfo = vk::makeDescriptorImageInfo(texSampler.get(), texView.get(), texLayout);
1577 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), descType, &descriptorImageInfo);
1578 updateBuilder.update(vkd, device);
1579
1580 // Shader modules.
1581 const auto vertexModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1582 const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1583
1584 // Render pass.
1585 const vk::VkAttachmentDescription fbAttachment =
1586 {
1587 0u, // VkAttachmentDescriptionFlags flags;
1588 m_params.format, // VkFormat format;
1589 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1590 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1591 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1592 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1593 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1594 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1595 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1596 };
1597
1598 const vk::VkAttachmentReference colorRef =
1599 {
1600 0u, // deUint32 attachment;
1601 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1602 };
1603
1604 const vk::VkSubpassDescription subpass =
1605 {
1606 0u, // VkSubpassDescriptionFlags flags;
1607 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1608 0u, // deUint32 inputAttachmentCount;
1609 nullptr, // const VkAttachmentReference* pInputAttachments;
1610 1u, // deUint32 colorAttachmentCount;
1611 &colorRef, // const VkAttachmentReference* pColorAttachments;
1612 0u, // const VkAttachmentReference* pResolveAttachments;
1613 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
1614 0u, // deUint32 preserveAttachmentCount;
1615 nullptr, // const deUint32* pPreserveAttachments;
1616 };
1617
1618 const vk::VkRenderPassCreateInfo renderPassInfo =
1619 {
1620 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1621 nullptr, // const void* pNext;
1622 0u, // VkRenderPassCreateFlags flags;
1623 1u, // deUint32 attachmentCount;
1624 &fbAttachment, // const VkAttachmentDescription* pAttachments;
1625 1u, // deUint32 subpassCount;
1626 &subpass, // const VkSubpassDescription* pSubpasses;
1627 0u, // deUint32 dependencyCount;
1628 nullptr, // const VkSubpassDependency* pDependencies;
1629 };
1630 const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo);
1631
1632 // Framebuffer.
1633 std::vector<vk::VkImageView> attachments;
1634 attachments.push_back(fbView.get());
1635 const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), 1u, &fbView.get(), texExtent.width, texExtent.height, texExtent.depth);
1636
1637 // Push constant range.
1638 const vk::VkPushConstantRange pcRange =
1639 {
1640 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
1641 0u, // deUint32 offset;
1642 static_cast<deUint32>(sizeof(ExactSamplingCase::PushConstants)), // deUint32 size;
1643 };
1644
1645 // Pipeline layout.
1646 const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo =
1647 {
1648 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1649 nullptr, // const void* pNext;
1650 0u, // VkPipelineLayoutCreateFlags flags;
1651 1u, // deUint32 setLayoutCount;
1652 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
1653 1u, // deUint32 pushConstantRangeCount;
1654 &pcRange, // const VkPushConstantRange* pPushConstantRanges;
1655 };
1656 const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutInfo);
1657
1658 // Graphics pipeline.
1659 const std::vector<vk::VkViewport> viewports (1u, vk::makeViewport(texExtent));
1660 const vk::VkRect2D renderArea = vk::makeRect2D(texExtent);
1661 const std::vector<vk::VkRect2D> scissors (1u, renderArea);
1662
1663 const auto vtxBindingDescription = ExactSamplingCase::VertexData::getBindingDescription();
1664 const auto vtxAttributeDescriptions = ExactSamplingCase::VertexData::getAttributeDescriptions();
1665
1666 const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
1667 {
1668 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
1669 nullptr, // const void* pNext
1670 0u, // VkPipelineVertexInputStateCreateFlags flags
1671 1u, // deUint32 vertexBindingDescriptionCount
1672 &vtxBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
1673 static_cast<deUint32>(vtxAttributeDescriptions.size()), // deUint32 vertexAttributeDescriptionCount
1674 vtxAttributeDescriptions.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
1675 };
1676
1677 const auto pipeline = vk::makeGraphicsPipeline(
1678 vkd, device, pipelineLayout.get(),
1679 vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
1680 renderPass.get(), viewports, scissors,
1681 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vertexInputInfo);
1682
1683 // Command pool and command buffer.
1684 const auto cmdPool = vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
1685 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1686 const auto cmdBuffer = cmdBufferPtr.get();
1687
1688 // Draw quad.
1689 const ExactSamplingCase::PushConstants pushConstants =
1690 {
1691 static_cast<float>(texExtent.width),
1692 static_cast<float>(texExtent.height),
1693 };
1694
1695 const tcu::Vec4 clearFbColor (0.0f, 0.0f, 0.0f, 1.0f);
1696 const vk::VkDeviceSize vertexBufferOffset = 0ull;
1697
1698 const auto vertexBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
1699 const auto preBufferCopyBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, texBuffer.get(), 0ull, texBufferSize);
1700 const auto preTexCopyBarrier = vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texImage.get(), colorSubresourceRange);
1701 const auto postTexCopyBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texLayout, texImage.get(), colorSubresourceRange);
1702 const auto texCopyRange = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1703 const auto texImageCopy = vk::makeBufferImageCopy(texExtent, texCopyRange);
1704
1705 vk::beginCommandBuffer(vkd, cmdBuffer);
1706
1707 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vertexBufferBarrier, 0u, nullptr);
1708 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 1u, &preBufferCopyBarrier, 0u, nullptr);
1709 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preTexCopyBarrier);
1710 vkd.cmdCopyBufferToImage(cmdBuffer, texBuffer.get(), texImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &texImageCopy);
1711 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postTexCopyBarrier);
1712
1713 vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, clearFbColor);
1714 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
1715 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1716 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1717 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
1718 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
1719 vk::endRenderPass(vkd, cmdBuffer);
1720
1721 vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), iImgSize);
1722
1723 vk::endCommandBuffer(vkd, cmdBuffer);
1724 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1725
1726 // Check results.
1727 const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
1728 vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
1729
1730 const auto resultsBufferPtr = reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
1731 const tcu::ConstPixelBufferAccess resultPixels {tcuFormat, iImgSize[0], iImgSize[1], 1, resultsBufferPtr};
1732
1733 const tcu::TextureFormat diffFormat {tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
1734 const auto diffBytes = tcu::getPixelSize(diffFormat) * iImgSize[0] * iImgSize[1];
1735 std::unique_ptr<deUint8[]> diffData {new deUint8[diffBytes]};
1736 const tcu::PixelBufferAccess diffImg {diffFormat, iImgSize[0], iImgSize[1], 1, diffData.get()};
1737
1738 const tcu::Vec4 colorRed {1.0f, 0.0f, 0.0f, 1.0f};
1739 const tcu::Vec4 colorGreen {0.0f, 1.0f, 0.0f, 1.0f};
1740
1741 // Clear diff image.
1742 deMemset(diffData.get(), 0, static_cast<size_t>(diffBytes));
1743
1744 bool pass = true;
1745 for (int x = 0; x < W; ++x)
1746 for (int y = 0; y < H; ++y)
1747 for (int z = 0; z < D; ++z)
1748 {
1749 const auto inPix = texPixels.getPixel(x, y, z);
1750 const auto outPix = resultPixels.getPixel(x, y, z);
1751 if (inPix == outPix)
1752 {
1753 diffImg.setPixel(colorGreen, x, y, z);
1754 }
1755 else
1756 {
1757 pass = false;
1758 diffImg.setPixel(colorRed, x, y, z);
1759 }
1760 }
1761
1762 tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1763 if (!pass)
1764 {
1765 auto& log = m_context.getTestContext().getLog();
1766 log << tcu::TestLog::Image("input", "Input texture", texPixels);
1767 log << tcu::TestLog::Image("output", "Rendered image", resultPixels);
1768 log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffImg);
1769 status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
1770 }
1771
1772 return status;
1773 }
1774
1775 } // anonymous
1776
createAllFormatsSamplerTests(tcu::TestContext & testCtx,bool separateStencilUsage=false)1777 tcu::TestCaseGroup* createAllFormatsSamplerTests (tcu::TestContext& testCtx, bool separateStencilUsage = false)
1778 {
1779 const struct
1780 {
1781 SamplerViewType type;
1782 const char* name;
1783 }
1784 imageViewTypes[] =
1785 {
1786 { VK_IMAGE_VIEW_TYPE_1D, "1d" },
1787 { { VK_IMAGE_VIEW_TYPE_1D, false }, "1d_unnormalized" },
1788 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
1789 { VK_IMAGE_VIEW_TYPE_2D, "2d" },
1790 { { VK_IMAGE_VIEW_TYPE_2D, false }, "2d_unnormalized" },
1791 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
1792 { VK_IMAGE_VIEW_TYPE_3D, "3d" },
1793 { VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
1794 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
1795 };
1796
1797 const VkFormat formats[] =
1798 {
1799 // Packed formats
1800 VK_FORMAT_R4G4_UNORM_PACK8,
1801 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1802 VK_FORMAT_R5G6B5_UNORM_PACK16,
1803 VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1804 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1805 VK_FORMAT_A2R10G10B10_UINT_PACK32,
1806 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1807 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
1808 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1809 VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1810 VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
1811 VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
1812
1813 // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
1814 VK_FORMAT_R8_SRGB,
1815 VK_FORMAT_R8G8B8_UINT,
1816 VK_FORMAT_B8G8R8A8_SINT,
1817 VK_FORMAT_R8G8_UNORM,
1818 VK_FORMAT_B8G8R8_SNORM,
1819 VK_FORMAT_R8G8B8A8_SNORM,
1820 VK_FORMAT_R8G8_UINT,
1821 VK_FORMAT_R8_SINT,
1822 VK_FORMAT_R8G8B8A8_SRGB,
1823 VK_FORMAT_R8G8B8A8_UNORM,
1824 VK_FORMAT_B8G8R8A8_UNORM,
1825 VK_FORMAT_B8G8R8_SRGB,
1826 VK_FORMAT_R8G8_SRGB,
1827 VK_FORMAT_R8_UINT,
1828 VK_FORMAT_R8G8B8A8_UINT,
1829 VK_FORMAT_R8G8_SINT,
1830 VK_FORMAT_R8_SNORM,
1831 VK_FORMAT_B8G8R8_SINT,
1832 VK_FORMAT_R8G8_SNORM,
1833 VK_FORMAT_B8G8R8_UNORM,
1834 VK_FORMAT_R8_UNORM,
1835
1836 // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
1837 VK_FORMAT_R32G32_SFLOAT,
1838 VK_FORMAT_R32G32B32_UINT,
1839 VK_FORMAT_R16G16B16A16_SFLOAT,
1840 VK_FORMAT_R16G16_UINT,
1841 VK_FORMAT_R32G32B32A32_SINT,
1842 VK_FORMAT_R16G16B16_SINT,
1843 VK_FORMAT_R16_SFLOAT,
1844 VK_FORMAT_R32_SINT,
1845 VK_FORMAT_R32_UINT,
1846 VK_FORMAT_R16G16B16_SFLOAT,
1847 VK_FORMAT_R16G16_SINT,
1848
1849 // More 16/32-bit formats required for testing VK_EXT_sampler_filter_minmax
1850 VK_FORMAT_R16_SNORM,
1851 VK_FORMAT_R32_SFLOAT,
1852
1853 // Scaled formats
1854 VK_FORMAT_R8G8B8A8_SSCALED,
1855 VK_FORMAT_A2R10G10B10_USCALED_PACK32,
1856
1857 // Compressed formats
1858 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
1859 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
1860 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
1861 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
1862 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
1863 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
1864 VK_FORMAT_EAC_R11_UNORM_BLOCK,
1865 VK_FORMAT_EAC_R11_SNORM_BLOCK,
1866 VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
1867 VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
1868 VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
1869 VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
1870 VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
1871 VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
1872 VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
1873 VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
1874 VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
1875 VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
1876 VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
1877 VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
1878
1879 // Depth formats required for testing VK_EXT_sampler_filter_minmax
1880 VK_FORMAT_D16_UNORM,
1881 VK_FORMAT_X8_D24_UNORM_PACK32,
1882 VK_FORMAT_D32_SFLOAT,
1883 VK_FORMAT_D16_UNORM_S8_UINT,
1884 VK_FORMAT_D24_UNORM_S8_UINT,
1885 VK_FORMAT_D32_SFLOAT_S8_UINT,
1886 };
1887
1888 de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", ""));
1889
1890 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
1891 {
1892 const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
1893 de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
1894 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats"));
1895
1896 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1897 {
1898 const VkFormat format = formats[formatNdx];
1899 const bool isCompressed = isCompressedFormat(format);
1900 const bool isDepthStencil = !isCompressed
1901 && tcu::hasDepthComponent(mapVkFormat(format).order) && tcu::hasStencilComponent(mapVkFormat(format).order);
1902 if (isCompressed)
1903 {
1904 // Do not use compressed formats with 1D and 1D array textures.
1905 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
1906 break;
1907 }
1908
1909 if (separateStencilUsage && !isDepthStencil)
1910 continue;
1911
1912 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
1913 getFormatCaseName(format).c_str(),
1914 (std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
1915
1916 if (!isCompressed && viewType.isNormalized())
1917 {
1918 // Do not include minFilter tests with compressed formats.
1919 // Randomly generated compressed textures are too noisy and will derive in false positives.
1920 de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(testCtx, viewType, format, separateStencilUsage);
1921 de::MovePtr<tcu::TestCaseGroup> minReduceFilterTests = createSamplerMinReduceFilterTests(testCtx, viewType, format, separateStencilUsage);
1922 formatGroup->addChild(minFilterTests.release());
1923 formatGroup->addChild(minReduceFilterTests.release());
1924 }
1925
1926 de::MovePtr<tcu::TestCaseGroup> magFilterTests = createSamplerMagFilterTests(testCtx, viewType, format, separateStencilUsage);
1927 formatGroup->addChild(magFilterTests.release());
1928
1929 if (viewType.isNormalized())
1930 {
1931 de::MovePtr<tcu::TestCaseGroup> magReduceFilterTests = createSamplerMagReduceFilterTests(testCtx, viewType, format, separateStencilUsage);
1932 de::MovePtr<tcu::TestCaseGroup> mipmapTests = createSamplerMipmapTests(testCtx, viewType, format, separateStencilUsage);
1933
1934 formatGroup->addChild(magReduceFilterTests.release());
1935 formatGroup->addChild(mipmapTests.release());
1936 }
1937
1938 if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
1939 {
1940 de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(testCtx, viewType, format, separateStencilUsage);
1941 formatGroup->addChild(addressModesTests.release());
1942 }
1943
1944 formatTests->addChild(formatGroup.release());
1945 }
1946
1947 viewTypeGroup->addChild(formatTests.release());
1948 viewTypeTests->addChild(viewTypeGroup.release());
1949 }
1950
1951 return viewTypeTests.release();
1952 }
1953
createExactSamplingTests(tcu::TestContext & testCtx)1954 tcu::TestCaseGroup* createExactSamplingTests (tcu::TestContext& testCtx)
1955 {
1956 de::MovePtr<tcu::TestCaseGroup> exactSamplingTests(new tcu::TestCaseGroup(testCtx, "exact_sampling", "Exact sampling tests"));
1957
1958 static const std::vector<vk::VkFormat> formats =
1959 {
1960 vk::VK_FORMAT_R8_SRGB,
1961 vk::VK_FORMAT_R8G8B8_UINT,
1962 vk::VK_FORMAT_B8G8R8A8_SINT,
1963 vk::VK_FORMAT_R8G8_UNORM,
1964 vk::VK_FORMAT_B8G8R8_SNORM,
1965 vk::VK_FORMAT_R8G8B8A8_SNORM,
1966 vk::VK_FORMAT_R8G8_UINT,
1967 vk::VK_FORMAT_R8_SINT,
1968 vk::VK_FORMAT_R8G8B8A8_SRGB,
1969 vk::VK_FORMAT_R8G8B8A8_UNORM,
1970 vk::VK_FORMAT_B8G8R8A8_UNORM,
1971 vk::VK_FORMAT_B8G8R8_SRGB,
1972 vk::VK_FORMAT_R8G8_SRGB,
1973 vk::VK_FORMAT_R8_UINT,
1974 vk::VK_FORMAT_R8G8B8A8_UINT,
1975 vk::VK_FORMAT_R8G8_SINT,
1976 vk::VK_FORMAT_R8_SNORM,
1977 vk::VK_FORMAT_B8G8R8_SINT,
1978 vk::VK_FORMAT_R8G8_SNORM,
1979 vk::VK_FORMAT_B8G8R8_UNORM,
1980 vk::VK_FORMAT_R8_UNORM,
1981
1982 vk::VK_FORMAT_R32G32_SFLOAT,
1983 vk::VK_FORMAT_R32G32B32_UINT,
1984 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
1985 vk::VK_FORMAT_R16G16_UINT,
1986 vk::VK_FORMAT_R32G32B32A32_SINT,
1987 vk::VK_FORMAT_R16G16B16_SINT,
1988 vk::VK_FORMAT_R16_SFLOAT,
1989 vk::VK_FORMAT_R32_SINT,
1990 vk::VK_FORMAT_R32_UINT,
1991 vk::VK_FORMAT_R16G16B16_SFLOAT,
1992 vk::VK_FORMAT_R16G16_SINT,
1993
1994 vk::VK_FORMAT_R16_SNORM,
1995 vk::VK_FORMAT_R32_SFLOAT,
1996 };
1997
1998 static const struct
1999 {
2000 const bool unnormalized;
2001 const std::string name;
2002 const std::string desc;
2003 } unnormalizedCoordinates[] =
2004 {
2005 { false, "normalized_coords", "Normalized coordinates" },
2006 { true, "unnormalized_coords", "Unnormalized coordinates" },
2007 };
2008
2009 static const struct
2010 {
2011 const tcu::Maybe<float> offset;
2012 const std::string name;
2013 const std::string desc;
2014 } testEdges[] =
2015 {
2016 { tcu::Nothing, "centered", "Sampling points centered in texel" },
2017 { tcu::just<float>(-1.0f), "edge_left", "Sampling points near left edge" },
2018 { tcu::just<float>(+1.0f), "edge_right", "Sampling points near right edge" },
2019 };
2020
2021 static const std::vector<std::pair<bool, std::string>> solidColor =
2022 {
2023 { false, "gradient" },
2024 { true, "solid_color" },
2025 };
2026
2027 for (const auto format : formats)
2028 {
2029 const std::string formatName = getFormatCaseName(format);
2030 const std::string description = std::string("Exact sampling tests with image format ") + getFormatName(format);
2031
2032 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), description.c_str()));
2033
2034 for (const auto& solid : solidColor)
2035 {
2036 de::MovePtr<tcu::TestCaseGroup> solidColorGroup(new tcu::TestCaseGroup(testCtx, solid.second.c_str(), ""));
2037
2038 for (int unIdx = 0; unIdx < DE_LENGTH_OF_ARRAY(unnormalizedCoordinates); ++unIdx)
2039 {
2040 const auto& unnorm = unnormalizedCoordinates[unIdx];
2041 de::MovePtr<tcu::TestCaseGroup> coordGroup (new tcu::TestCaseGroup(testCtx, unnorm.name.c_str(), unnorm.desc.c_str()));
2042
2043 for (int edgeIdx = 0; edgeIdx < DE_LENGTH_OF_ARRAY(testEdges); ++edgeIdx)
2044 {
2045 const auto& edges = testEdges[edgeIdx];
2046 const ExactSamplingCase::Params params = { format, unnorm.unnormalized, solid.first, edges.offset };
2047 coordGroup->addChild(new ExactSamplingCase{testCtx, edges.name, edges.desc, params});
2048 }
2049
2050 solidColorGroup->addChild(coordGroup.release());
2051 }
2052
2053 formatGroup->addChild(solidColorGroup.release());
2054 }
2055
2056 exactSamplingTests->addChild(formatGroup.release());
2057 }
2058
2059 return exactSamplingTests.release();
2060 }
2061
createSamplerTests(tcu::TestContext & testCtx)2062 tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx)
2063 {
2064 de::MovePtr<tcu::TestCaseGroup> samplerTests(new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests"));
2065 {
2066 samplerTests->addChild(createAllFormatsSamplerTests(testCtx));
2067 samplerTests->addChild(createExactSamplingTests(testCtx));
2068 }
2069
2070 // tests for VK_EXT_separate_stencil_usage
2071 de::MovePtr<tcu::TestCaseGroup> separateStencilUsageSamplerTests (new tcu::TestCaseGroup(testCtx, "separate_stencil_usage", "testing VK_EXT_separate_stencil_uasge"));
2072 {
2073 separateStencilUsageSamplerTests->addChild(createAllFormatsSamplerTests(testCtx, true));
2074 samplerTests->addChild(separateStencilUsageSamplerTests.release());
2075 }
2076
2077 // Border color swizzle tests.
2078 samplerTests->addChild(createSamplerBorderSwizzleTests(testCtx));
2079
2080 return samplerTests.release();
2081 }
2082
2083 } // pipeline
2084 } // vkt
2085