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 Sampler Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineSamplerTests.hpp"
28 #include "vktPipelineImageSamplingInstance.hpp"
29 #ifndef CTS_USES_VULKANSC
30 #include "vktPipelineSamplerBorderSwizzleTests.hpp"
31 #endif // CTS_USES_VULKANSC
32 #include "vktPipelineImageUtil.hpp"
33 #include "vktPipelineVertexUtil.hpp"
34 #include "vktTestCase.hpp"
35
36 #include "vkImageUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkObjUtil.hpp"
40 #include "vkBuilderUtil.hpp"
41 #include "vkBarrierUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkPrograms.hpp"
44 #include "vkImageWithMemory.hpp"
45 #include "vkBufferWithMemory.hpp"
46
47 #include "tcuPlatform.hpp"
48 #include "tcuTextureUtil.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuMaybe.hpp"
51 #include "tcuImageCompare.hpp"
52
53 #include "deStringUtil.hpp"
54 #include "deMemory.h"
55
56 #include <iomanip>
57 #include <sstream>
58 #include <vector>
59 #include <string>
60 #include <memory>
61 #include <utility>
62 #include <algorithm>
63
64 namespace vkt
65 {
66 namespace pipeline
67 {
68
69 using namespace vk;
70 using de::MovePtr;
71
72 namespace
73 {
74
75 class SamplerViewType
76 {
77 public:
SamplerViewType(vk::VkImageViewType type,bool normalized=true)78 SamplerViewType (vk::VkImageViewType type, bool normalized = true)
79 : m_viewType(type), m_normalized(normalized)
80 {
81 if (!normalized)
82 DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
83 }
84
operator vk::VkImageViewType() const85 operator vk::VkImageViewType () const
86 {
87 return m_viewType;
88 }
89
isNormalized() const90 bool isNormalized () const
91 {
92 return m_normalized;
93 }
94
95 private:
96 vk::VkImageViewType m_viewType;
97 bool m_normalized;
98 };
99
100 class SamplerTest : public vkt::TestCase
101 {
102 public:
103 SamplerTest (tcu::TestContext& testContext,
104 const char* name,
105 PipelineConstructionType pipelineConstructionType,
106 SamplerViewType imageViewType,
107 VkFormat imageFormat,
108 int imageSize,
109 float samplerLod,
110 bool separateStencilUsage,
111 bool sampleStencil);
~SamplerTest(void)112 virtual ~SamplerTest (void) {}
113
114 virtual ImageSamplingInstanceParams getImageSamplingInstanceParams (SamplerViewType imageViewType,
115 VkFormat imageFormat,
116 int imageSize,
117 float samplerLod,
118 bool separateStencilUsage,
119 bool sampleStencil) const;
120
121 tcu::Vec4 swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const;
122 virtual void initPrograms (SourceCollections& sourceCollections) const;
123 virtual void checkSupport (Context& context) const;
124 virtual TestInstance* createInstance (Context& context) const;
125 virtual tcu::UVec2 getRenderSize (SamplerViewType viewType) const;
126 virtual std::vector<Vertex4Tex4> createVertices (void) const;
127 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
128 virtual VkComponentMapping getComponentMapping (void) const;
129
130 static std::string getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type, bool sampleStencil);
131 static tcu::IVec3 getImageSize (SamplerViewType viewType, int size);
132 static int getArraySize (SamplerViewType viewType);
133
134 protected:
135 PipelineConstructionType m_pipelineConstructionType;
136 SamplerViewType m_imageViewType;
137 VkFormat m_imageFormat;
138 int m_imageSize;
139 float m_samplerLod;
140 bool m_separateStencilUsage;
141 bool m_sampleStencil;
142 };
143
144 class SamplerMagFilterTest : public SamplerTest
145 {
146 public:
147 SamplerMagFilterTest (tcu::TestContext& testContext,
148 const char* name,
149 PipelineConstructionType pipelineConstructionType,
150 SamplerViewType imageViewType,
151 VkFormat imageFormat,
152 VkFilter magFilter,
153 bool separateStencilUsage);
~SamplerMagFilterTest(void)154 virtual ~SamplerMagFilterTest (void) {}
155 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
156
157 private:
158 VkFilter m_magFilter;
159 };
160
161 class SamplerMinFilterTest : public SamplerTest
162 {
163 public:
164 SamplerMinFilterTest (tcu::TestContext& testContext,
165 const char* name,
166 PipelineConstructionType pipelineConstructionType,
167 SamplerViewType imageViewType,
168 VkFormat imageFormat,
169 VkFilter minFilter,
170 bool separateStencilUsage);
~SamplerMinFilterTest(void)171 virtual ~SamplerMinFilterTest (void) {}
172 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
173
174 private:
175 VkFilter m_minFilter;
176 };
177
178 class SamplerMagReduceFilterTest : public SamplerMagFilterTest
179 {
180 public:
181 SamplerMagReduceFilterTest (tcu::TestContext& testContext,
182 const char* name,
183 PipelineConstructionType pipelineConstructionType,
184 SamplerViewType imageViewType,
185 VkFormat imageFormat,
186 VkComponentMapping componentMapping,
187 VkSamplerReductionMode reductionMode,
188 bool separateStencilUsage);
189
~SamplerMagReduceFilterTest(void)190 virtual ~SamplerMagReduceFilterTest (void) {}
191 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
192 virtual VkComponentMapping getComponentMapping (void) const;
193
194 private:
195 const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
196 VkComponentMapping m_componentMapping;
197 };
198
199 class SamplerMinReduceFilterTest : public SamplerMinFilterTest
200 {
201 public:
202 SamplerMinReduceFilterTest (tcu::TestContext& testContext,
203 const char* name,
204 PipelineConstructionType pipelineConstructionType,
205 SamplerViewType imageViewType,
206 VkFormat imageFormat,
207 VkComponentMapping componentMapping,
208 VkSamplerReductionMode reductionMode,
209 bool separateStencilUsage);
210
~SamplerMinReduceFilterTest(void)211 virtual ~SamplerMinReduceFilterTest (void) {}
212 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
213 virtual VkComponentMapping getComponentMapping (void) const;
214
215 private:
216 const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
217 VkComponentMapping m_componentMapping;
218 };
219
220 class SamplerLodTest : public SamplerTest
221 {
222 public:
223 SamplerLodTest (tcu::TestContext& testContext,
224 const char* name,
225 PipelineConstructionType pipelineConstructionType,
226 SamplerViewType imageViewType,
227 VkFormat imageFormat,
228 VkSamplerMipmapMode mipmapMode,
229 float minLod,
230 float maxLod,
231 float mipLodBias,
232 float samplerLod,
233 bool separateStencilUsage);
~SamplerLodTest(void)234 virtual ~SamplerLodTest (void) {}
235 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
236 virtual void checkSupport (Context& context) const;
237
238 private:
239 VkSamplerMipmapMode m_mipmapMode;
240 float m_minLod;
241 float m_maxLod;
242 float m_mipLodBias;
243 };
244
checkSupport(Context & context) const245 void SamplerLodTest::checkSupport (Context& context) const
246 {
247 SamplerTest::checkSupport(context);
248
249 #ifndef CTS_USES_VULKANSC
250 if (m_mipLodBias != 0.0f && context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
251 !context.getPortabilitySubsetFeatures().samplerMipLodBias)
252 {
253 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Sampler mipmap LOD bias is not supported by this implementation");
254 }
255 #endif // CTS_USES_VULKANSC
256 }
257
258 class SamplerAddressModesTest : public SamplerTest
259 {
260 public:
261 SamplerAddressModesTest (tcu::TestContext& testContext,
262 const char* name,
263 PipelineConstructionType pipelineConstructionType,
264 SamplerViewType imageViewType,
265 VkFormat imageFormat,
266 VkSamplerAddressMode addressU,
267 VkSamplerAddressMode addressV,
268 VkSamplerAddressMode addressW,
269 VkBorderColor borderColor,
270 rr::GenericVec4 customBorderColorValue,
271 bool customBorderColorFormatless,
272 bool separateStencilUsage,
273 bool sampleStencil);
~SamplerAddressModesTest(void)274 virtual ~SamplerAddressModesTest (void) {}
275 virtual tcu::UVec2 getRenderSize (SamplerViewType viewType) const;
276 virtual std::vector<Vertex4Tex4> createVertices (void) const;
277 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
278
279 VkSamplerCustomBorderColorCreateInfoEXT getSamplerCustomBorderColorCreateInfo (VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const;
280
281 private:
282 VkSamplerAddressMode m_addressU;
283 VkSamplerAddressMode m_addressV;
284 VkSamplerAddressMode m_addressW;
285 VkBorderColor m_borderColor;
286
287 const VkSamplerCustomBorderColorCreateInfoEXT m_customBorderColorCreateInfo;
288 };
289
290
291 // SamplerTest
292
SamplerTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,float samplerLod,bool separateStencilUsage,bool sampleStencil)293 SamplerTest::SamplerTest (tcu::TestContext& testContext,
294 const char* name,
295 PipelineConstructionType pipelineConstructionType,
296 SamplerViewType imageViewType,
297 VkFormat imageFormat,
298 int imageSize,
299 float samplerLod,
300 bool separateStencilUsage,
301 bool sampleStencil)
302 : vkt::TestCase (testContext, name)
303 , m_pipelineConstructionType (pipelineConstructionType)
304 , m_imageViewType (imageViewType)
305 , m_imageFormat (imageFormat)
306 , m_imageSize (imageSize)
307 , m_samplerLod (samplerLod)
308 , m_separateStencilUsage (separateStencilUsage)
309 , m_sampleStencil (sampleStencil)
310 {
311 // Can't do both at the same time with the current code.
312 DE_ASSERT(!separateStencilUsage || !sampleStencil);
313 }
314
getImageSamplingInstanceParams(SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,float samplerLod,bool separateStencilUsage,bool sampleStencil) const315 ImageSamplingInstanceParams SamplerTest::getImageSamplingInstanceParams (SamplerViewType imageViewType,
316 VkFormat imageFormat,
317 int imageSize,
318 float samplerLod,
319 bool separateStencilUsage,
320 bool sampleStencil) const
321 {
322 const tcu::UVec2 renderSize = getRenderSize(imageViewType);
323 const std::vector<Vertex4Tex4> vertices = createVertices();
324 const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo();
325 const VkComponentMapping componentMapping = getComponentMapping();
326
327 const auto isDSFormat = isDepthStencilFormat(imageFormat);
328 const auto tcuFormat = (isDSFormat ? mapVkFormat(imageFormat) : tcu::TextureFormat());
329 const auto hasDepth = (isDSFormat && tcu::hasDepthComponent(tcuFormat.order));
330 const auto hasStencil = (isDSFormat && tcu::hasStencilComponent(tcuFormat.order));
331 const auto imageAspect = (isDSFormat ? (sampleStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT) : VK_IMAGE_ASPECT_COLOR_BIT);
332 const deUint32 mipLevels = (imageViewType.isNormalized() ? static_cast<deUint32>(deLog2Floor32(imageSize)) + 1u : 1u);
333
334 DE_UNREF(hasDepth); // For debug builds.
335 DE_UNREF(hasStencil); // For debug builds.
336 DE_ASSERT(imageAspect != VK_IMAGE_ASPECT_DEPTH_BIT || hasDepth);
337 DE_ASSERT(imageAspect != VK_IMAGE_ASPECT_STENCIL_BIT || hasStencil);
338
339 const VkImageSubresourceRange subresourceRange =
340 {
341 (VkImageAspectFlags)imageAspect, // VkImageAspectFlags aspectMask;
342 0u, // deUint32 baseMipLevel;
343 mipLevels, // deUint32 mipLevels;
344 0u, // deUint32 baseArrayLayer;
345 (deUint32)SamplerTest::getArraySize(imageViewType) // deUint32 arraySize;
346 };
347
348 return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat,
349 getImageSize(imageViewType, imageSize),
350 getArraySize(imageViewType),
351 componentMapping, subresourceRange,
352 samplerParams, samplerLod, vertices, separateStencilUsage);
353 }
354
checkSupport(Context & context) const355 void SamplerTest::checkSupport (Context& context) const
356 {
357 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
358 #ifndef CTS_USES_VULKANSC
359 if (m_imageFormat == VK_FORMAT_A8_UNORM_KHR || m_imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
360 context.requireDeviceFunctionality("VK_KHR_maintenance5");
361 #endif // CTS_USES_VULKANSC
362 checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage, m_sampleStencil));
363 }
364
swizzle(tcu::Vec4 inputData,VkComponentMapping componentMapping,float zeroOrOneValue) const365 tcu::Vec4 SamplerTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const
366 {
367 // Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
368 const vk::VkComponentMapping nonIdentityMapping =
369 {
370 componentMapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : componentMapping.r,
371 componentMapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : componentMapping.g,
372 componentMapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : componentMapping.b,
373 componentMapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : componentMapping.a
374
375 };
376 // array map with enum VkComponentSwizzle
377 const float channelValues[] =
378 {
379 -1.0f, // impossible
380 zeroOrOneValue, // SWIZZLE_0
381 zeroOrOneValue, // SWIZZLE_1
382 inputData.x(),
383 inputData.y(),
384 inputData.z(),
385 inputData.w(),
386 -1.0f
387 };
388
389 return tcu::Vec4(channelValues[nonIdentityMapping.r],
390 channelValues[nonIdentityMapping.g],
391 channelValues[nonIdentityMapping.b],
392 channelValues[nonIdentityMapping.a]);
393 }
394
initPrograms(SourceCollections & sourceCollections) const395 void SamplerTest::initPrograms (SourceCollections& sourceCollections) const
396 {
397 std::ostringstream vertexSrc;
398 std::ostringstream fragmentSrc;
399 const char* texCoordSwizzle = DE_NULL;
400 tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
401 : mapVkFormat(m_imageFormat);
402 tcu::Vec4 lookupScale;
403 tcu::Vec4 lookupBias;
404
405 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, m_sampleStencil);
406
407 tcu::Vec4 swizzledScale = swizzle(lookupScale, getComponentMapping(), 1.0f);
408 tcu::Vec4 swizzledBias = swizzle(lookupBias, getComponentMapping(), 0.0f);
409
410 switch (m_imageViewType)
411 {
412 case VK_IMAGE_VIEW_TYPE_1D:
413 texCoordSwizzle = "x";
414 break;
415 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
416 case VK_IMAGE_VIEW_TYPE_2D:
417 texCoordSwizzle = "xy";
418 break;
419 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
420 case VK_IMAGE_VIEW_TYPE_3D:
421 case VK_IMAGE_VIEW_TYPE_CUBE:
422 texCoordSwizzle = "xyz";
423 break;
424 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
425 texCoordSwizzle = "xyzw";
426 break;
427 default:
428 DE_ASSERT(false);
429 break;
430 }
431
432 vertexSrc << "#version 440\n"
433 << "layout(location = 0) in vec4 position;\n"
434 << "layout(location = 1) in vec4 texCoords;\n"
435 << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
436 << "out gl_PerVertex {\n"
437 << " vec4 gl_Position;\n"
438 << "};\n"
439 << "void main (void)\n"
440 << "{\n"
441 << " gl_Position = position;\n"
442 << " vtxTexCoords = texCoords;\n"
443 << "}\n";
444
445 fragmentSrc << "#version 440\n"
446 << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType, m_sampleStencil) << " texSampler;\n"
447 << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
448 << "layout(location = 0) out highp vec4 fragColor;\n"
449 << "void main (void)\n"
450 << "{\n"
451 << " fragColor = ";
452
453 if (m_samplerLod > 0.0f || !m_imageViewType.isNormalized())
454 {
455 DE_ASSERT(m_imageViewType.isNormalized() || (m_samplerLod == 0.0f && !m_imageViewType.isNormalized()));
456 fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
457 }
458 else
459 {
460 fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
461 }
462
463 fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
464 << "}\n";
465
466 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
467 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
468 }
469
createInstance(Context & context) const470 TestInstance* SamplerTest::createInstance (Context& context) const
471 {
472 return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage, m_sampleStencil));
473 }
474
getRenderSize(SamplerViewType viewType) const475 tcu::UVec2 SamplerTest::getRenderSize (SamplerViewType viewType) const
476 {
477 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
478 {
479 return tcu::UVec2(16u, 16u);
480 }
481 else
482 {
483 return tcu::UVec2(16u * 3u, 16u * 2u);
484 }
485 }
486
createVertices(void) const487 std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const
488 {
489 std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
490 // Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries.
491 // TODO: Would be nice to base this on number of texels and subtexel precision. But this
492 // seems to work.
493 for (unsigned int i = 0; i < vertices.size(); ++i) {
494 vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f);
495 if (!m_imageViewType.isNormalized()) {
496 const float imageSize = static_cast<float>(m_imageSize);
497 for (int j = 0; j < tcu::Vec4::SIZE; ++j)
498 vertices[i].texCoord[j] *= imageSize;
499 }
500 }
501 return vertices;
502 }
503
getSamplerCreateInfo(void) const504 VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const
505 {
506 const VkSamplerCreateInfo defaultSamplerParams =
507 {
508 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
509 DE_NULL, // const void* pNext;
510 0u, // VkSamplerCreateFlags flags;
511 VK_FILTER_NEAREST, // VkFilter magFilter;
512 VK_FILTER_NEAREST, // VkFilter minFilter;
513 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
514 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
515 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
516 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
517 0.0f, // float mipLodBias;
518 VK_FALSE, // VkBool32 anisotropyEnable;
519 1.0f, // float maxAnisotropy;
520 false, // VkBool32 compareEnable;
521 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
522 0.0f, // float minLod;
523 (m_imageViewType.isNormalized() ? 0.25f : 0.0f), // float maxLod;
524 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat, m_sampleStencil), // VkBorderColor borderColor;
525 !m_imageViewType.isNormalized(), // VkBool32 unnormalizedCoordinates;
526 };
527
528 return defaultSamplerParams;
529 }
530
getComponentMapping(void) const531 VkComponentMapping SamplerTest::getComponentMapping (void) const
532 {
533 const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
534 return componentMapping;
535 }
536
getGlslSamplerType(const tcu::TextureFormat & format,SamplerViewType type,bool sampleStencil)537 std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type, bool sampleStencil)
538 {
539 std::ostringstream samplerType;
540
541 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER || sampleStencil)
542 samplerType << "u";
543 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
544 samplerType << "i";
545
546 switch (type)
547 {
548 case VK_IMAGE_VIEW_TYPE_1D:
549 samplerType << "sampler1D";
550 break;
551
552 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
553 samplerType << "sampler1DArray";
554 break;
555
556 case VK_IMAGE_VIEW_TYPE_2D:
557 samplerType << "sampler2D";
558 break;
559
560 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
561 samplerType << "sampler2DArray";
562 break;
563
564 case VK_IMAGE_VIEW_TYPE_3D:
565 samplerType << "sampler3D";
566 break;
567
568 case VK_IMAGE_VIEW_TYPE_CUBE:
569 samplerType << "samplerCube";
570 break;
571
572 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
573 samplerType << "samplerCubeArray";
574 break;
575
576 default:
577 DE_FATAL("Unknown image view type");
578 break;
579 }
580
581 return samplerType.str();
582 }
583
getImageSize(SamplerViewType viewType,int size)584 tcu::IVec3 SamplerTest::getImageSize (SamplerViewType viewType, int size)
585 {
586 switch (viewType)
587 {
588 case VK_IMAGE_VIEW_TYPE_1D:
589 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
590 return tcu::IVec3(size, 1, 1);
591
592 case VK_IMAGE_VIEW_TYPE_3D:
593 return tcu::IVec3(size, size, 4);
594
595 default:
596 break;
597 }
598
599 return tcu::IVec3(size, size, 1);
600 }
601
getArraySize(SamplerViewType viewType)602 int SamplerTest::getArraySize (SamplerViewType viewType)
603 {
604 switch (viewType)
605 {
606 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
607 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
608 case VK_IMAGE_VIEW_TYPE_CUBE:
609 return 6;
610
611 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
612 return 36;
613
614 default:
615 break;
616 }
617
618 return 1;
619 }
620
621
622 // SamplerMagFilterTest
623
SamplerMagFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkFilter magFilter,bool separateStencilUsage)624 SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext& testContext,
625 const char* name,
626 PipelineConstructionType pipelineConstructionType,
627 SamplerViewType imageViewType,
628 VkFormat imageFormat,
629 VkFilter magFilter,
630 bool separateStencilUsage)
631 : SamplerTest (testContext, name, pipelineConstructionType, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage, false)
632 , m_magFilter (magFilter)
633 {
634 }
635
getSamplerCreateInfo(void) const636 VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const
637 {
638 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
639 samplerParams.magFilter = m_magFilter;
640
641 return samplerParams;
642 }
643
644
645 // SamplerMinFilterTest
646
SamplerMinFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkFilter minFilter,bool separateStencilUsage)647 SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext& testContext,
648 const char* name,
649 PipelineConstructionType pipelineConstructionType,
650 SamplerViewType imageViewType,
651 VkFormat imageFormat,
652 VkFilter minFilter,
653 bool separateStencilUsage)
654 : SamplerTest (testContext, name, pipelineConstructionType, imageViewType, imageFormat, 32, 0.0f, separateStencilUsage, false)
655 , m_minFilter (minFilter)
656 {
657 }
658
getSamplerCreateInfo(void) const659 VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const
660 {
661 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
662 samplerParams.minFilter = m_minFilter;
663 // set minLod to epsilon, to force use of the minFilter
664 samplerParams.minLod = 0.01f;
665
666 return samplerParams;
667 }
668
669
670 namespace
671 {
672
getSamplerReductionCreateInfo(VkSamplerReductionMode reductionMode)673 VkSamplerReductionModeCreateInfo getSamplerReductionCreateInfo (VkSamplerReductionMode reductionMode)
674 {
675 const VkSamplerReductionModeCreateInfo ret =
676 {
677 VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, // VkStructureType sType
678 DE_NULL, // const void* pNext
679 reductionMode // VkSamplerReductionMode reductionMode
680 };
681 return ret;
682 }
683
684 }
685
686
687 // SamplerMagReduceFilterTest
688
SamplerMagReduceFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkComponentMapping componentMapping,VkSamplerReductionMode reductionMode,bool separateStencilUsage)689 SamplerMagReduceFilterTest::SamplerMagReduceFilterTest (tcu::TestContext& testContext,
690 const char* name,
691 PipelineConstructionType pipelineConstructionType,
692 SamplerViewType imageViewType,
693 VkFormat imageFormat,
694 VkComponentMapping componentMapping,
695 VkSamplerReductionMode reductionMode,
696 bool separateStencilUsage)
697 : SamplerMagFilterTest (testContext, name, pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
698 , m_reductionCreaterInfo (getSamplerReductionCreateInfo(reductionMode))
699 , m_componentMapping (componentMapping)
700 {
701 }
702
getSamplerCreateInfo(void) const703 VkSamplerCreateInfo SamplerMagReduceFilterTest::getSamplerCreateInfo (void) const
704 {
705 VkSamplerCreateInfo samplerParams = SamplerMagFilterTest::getSamplerCreateInfo();
706
707 samplerParams.pNext = &m_reductionCreaterInfo;
708
709 return samplerParams;
710 }
711
getComponentMapping(void) const712 VkComponentMapping SamplerMagReduceFilterTest::getComponentMapping (void) const
713 {
714 return m_componentMapping;
715 }
716
717 // SamplerMinReduceFilterTest
718
SamplerMinReduceFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkComponentMapping componentMapping,VkSamplerReductionMode reductionMode,bool separateStencilUsage)719 SamplerMinReduceFilterTest::SamplerMinReduceFilterTest (tcu::TestContext& testContext,
720 const char* name,
721 PipelineConstructionType pipelineConstructionType,
722 SamplerViewType imageViewType,
723 VkFormat imageFormat,
724 VkComponentMapping componentMapping,
725 VkSamplerReductionMode reductionMode,
726 bool separateStencilUsage)
727 : SamplerMinFilterTest (testContext, name, pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
728 , m_reductionCreaterInfo (getSamplerReductionCreateInfo(reductionMode))
729 , m_componentMapping (componentMapping)
730 {
731 }
732
getSamplerCreateInfo(void) const733 VkSamplerCreateInfo SamplerMinReduceFilterTest::getSamplerCreateInfo (void) const
734 {
735 VkSamplerCreateInfo samplerParams = SamplerMinFilterTest::getSamplerCreateInfo();
736
737 samplerParams.pNext = &m_reductionCreaterInfo;
738
739 return samplerParams;
740 }
741
getComponentMapping(void) const742 VkComponentMapping SamplerMinReduceFilterTest::getComponentMapping (void) const
743 {
744 return m_componentMapping;
745 }
746
747 // SamplerLodTest
748
SamplerLodTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerMipmapMode mipmapMode,float minLod,float maxLod,float mipLodBias,float samplerLod,bool separateStencilUsage)749 SamplerLodTest::SamplerLodTest (tcu::TestContext& testContext,
750 const char* name,
751 PipelineConstructionType pipelineConstructionType,
752 SamplerViewType imageViewType,
753 VkFormat imageFormat,
754 VkSamplerMipmapMode mipmapMode,
755 float minLod,
756 float maxLod,
757 float mipLodBias,
758 float samplerLod,
759 bool separateStencilUsage)
760 : SamplerTest (testContext, name, pipelineConstructionType, imageViewType, imageFormat, 32, samplerLod, separateStencilUsage, false)
761 , m_mipmapMode (mipmapMode)
762 , m_minLod (minLod)
763 , m_maxLod (maxLod)
764 , m_mipLodBias (mipLodBias)
765 {
766 }
767
getSamplerCreateInfo(void) const768 VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const
769 {
770 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
771
772 samplerParams.mipmapMode = m_mipmapMode;
773 samplerParams.minLod = m_minLod;
774 samplerParams.maxLod = m_maxLod;
775 samplerParams.mipLodBias = m_mipLodBias;
776
777 return samplerParams;
778 }
779
780
781 // SamplerAddressModesTest
782
SamplerAddressModesTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerAddressMode addressU,VkSamplerAddressMode addressV,VkSamplerAddressMode addressW,VkBorderColor borderColor,rr::GenericVec4 customBorderColorValue,bool customBorderColorFormatless,bool separateStencilUsage,bool sampleStencil)783 SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext& testContext,
784 const char* name,
785 PipelineConstructionType pipelineConstructionType,
786 SamplerViewType imageViewType,
787 VkFormat imageFormat,
788 VkSamplerAddressMode addressU,
789 VkSamplerAddressMode addressV,
790 VkSamplerAddressMode addressW,
791 VkBorderColor borderColor,
792 rr::GenericVec4 customBorderColorValue,
793 bool customBorderColorFormatless,
794 bool separateStencilUsage,
795 bool sampleStencil)
796 : SamplerTest (testContext, name, pipelineConstructionType, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage, sampleStencil)
797 , m_addressU (addressU)
798 , m_addressV (addressV)
799 , m_addressW (addressW)
800 , m_borderColor (borderColor)
801 , m_customBorderColorCreateInfo (getSamplerCustomBorderColorCreateInfo(imageFormat, customBorderColorValue, customBorderColorFormatless))
802 {
803 }
804
getRenderSize(SamplerViewType viewType) const805 tcu::UVec2 SamplerAddressModesTest::getRenderSize (SamplerViewType viewType) const
806 {
807 return 4u * SamplerTest::getRenderSize(viewType);
808 }
809
createVertices(void) const810 std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const
811 {
812 std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
813
814 switch (m_imageViewType)
815 {
816 case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
817 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
818 vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
819
820 break;
821
822 case VK_IMAGE_VIEW_TYPE_2D:
823 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
824 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
825 vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
826
827 break;
828
829 case VK_IMAGE_VIEW_TYPE_3D:
830 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
831 vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
832
833 break;
834
835 case VK_IMAGE_VIEW_TYPE_CUBE:
836 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
837 break;
838
839 default:
840 DE_ASSERT(false);
841 }
842
843 return vertices;
844 }
845
getSamplerCreateInfo(void) const846 VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const
847 {
848 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
849 samplerParams.addressModeU = m_addressU;
850 samplerParams.addressModeV = m_addressV;
851 samplerParams.addressModeW = m_addressW;
852 samplerParams.borderColor = m_borderColor;
853
854 if (m_borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
855 m_borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT)
856 {
857 samplerParams.pNext = &m_customBorderColorCreateInfo;
858 }
859
860 return samplerParams;
861 }
862
getSamplerCustomBorderColorCreateInfo(VkFormat format,rr::GenericVec4 customBorderColorValue,bool customBorderColorFormatless) const863 VkSamplerCustomBorderColorCreateInfoEXT SamplerAddressModesTest::getSamplerCustomBorderColorCreateInfo (VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const
864 {
865 const VkSamplerCustomBorderColorCreateInfoEXT defaultSamplerCustomBorderColorParams =
866 {
867 VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
868 DE_NULL,
869 mapVkColor(customBorderColorValue),
870 customBorderColorFormatless ? VK_FORMAT_UNDEFINED : format
871 };
872
873 return defaultSamplerCustomBorderColorParams;
874 }
875
876
877 // Utilities to create test nodes
878
getFormatCaseName(const VkFormat format)879 std::string getFormatCaseName (const VkFormat format)
880 {
881 const std::string fullName = getFormatName(format);
882
883 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
884
885 return de::toLower(fullName.substr(10));
886 }
887
createSamplerMagFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)888 MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
889 {
890 // Tests for magnification filter
891 MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter"));
892
893 if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
894 // Magnifies image using VK_FILTER_LINEAR
895 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
896 // Magnifies image using VK_FILTER_NEAREST
897 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
898
899 return samplerMagFilterTests;
900 }
901
createSamplerMinFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)902 MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
903 {
904 MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter"));
905
906 if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
907 // Minifies image using VK_FILTER_LINEAR
908 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
909 // Minifies image using VK_FILTER_NEAREST
910 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
911
912 return samplerMinFilterTests;
913 }
914
915 const VkComponentMapping reduceFilterComponentMappings[] =
916 {
917 // filterMinmaxImageComponentMapping == false - compatible mappings:
918 { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO },
919 { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO },
920
921 // other mappings
922 { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A },
923 { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A },
924 { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R },
925 };
926
getShortComponentSwizzleName(VkComponentSwizzle componentSwizzle)927 static std::string getShortComponentSwizzleName (VkComponentSwizzle componentSwizzle)
928 {
929 const std::string fullName = getComponentSwizzleName(componentSwizzle);
930 const char* prefix = "VK_COMPONENT_SWIZZLE_";
931
932 DE_ASSERT(de::beginsWith(fullName, prefix));
933
934 return de::toLower(fullName.substr(deStrnlen(prefix, -1)));
935 }
936
getComponentMappingGroupName(const VkComponentMapping & componentMapping)937 static std::string getComponentMappingGroupName (const VkComponentMapping& componentMapping)
938 {
939 std::ostringstream name;
940
941 name << "comp_";
942
943 name << getShortComponentSwizzleName(componentMapping.r) << "_"
944 << getShortComponentSwizzleName(componentMapping.g) << "_"
945 << getShortComponentSwizzleName(componentMapping.b) << "_"
946 << getShortComponentSwizzleName(componentMapping.a);
947
948 return name.str();
949 }
950
createSamplerMagReduceFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)951 MovePtr<tcu::TestCaseGroup> createSamplerMagReduceFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
952 {
953 MovePtr<tcu::TestCaseGroup> samplerMagReduceFilterTests (new tcu::TestCaseGroup(testCtx, "mag_reduce", "Tests for magnification reduce filter"));
954
955 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
956 {
957 const VkComponentMapping& mapping = reduceFilterComponentMappings[i];
958
959 MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
960
961 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
962 {
963 // Magnifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE
964 componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "average", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, separateStencilUsage));
965 }
966 // Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN
967 componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "min", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN, separateStencilUsage));
968 // Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX
969 componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "max", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX, separateStencilUsage));
970 samplerMagReduceFilterTests->addChild(componentGroup.release());
971 }
972 return samplerMagReduceFilterTests;
973 }
974
createSamplerMinReduceFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)975 MovePtr<tcu::TestCaseGroup> createSamplerMinReduceFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
976 {
977 MovePtr<tcu::TestCaseGroup> samplerMinReduceFilterTests (new tcu::TestCaseGroup(testCtx, "min_reduce", "Tests for minification reduce filter"));
978
979 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
980 {
981 const VkComponentMapping& mapping = reduceFilterComponentMappings[i];
982
983 MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
984
985 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
986 {
987 // Minifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE
988 componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "average", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, separateStencilUsage));
989 }
990 // Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN
991 componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "min", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN, separateStencilUsage));
992 // Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX
993 componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "max", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX, separateStencilUsage));
994 samplerMinReduceFilterTests->addChild(componentGroup.release());
995 }
996 return samplerMinReduceFilterTests;
997 }
998
createSamplerLodTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerMipmapMode mipmapMode,bool separateStencilUsage)999 MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, bool separateStencilUsage)
1000 {
1001 struct TestCaseConfig
1002 {
1003 const char* name;
1004 float minLod;
1005 float maxLod;
1006 float mipLodBias;
1007 float lod;
1008 };
1009
1010 TestCaseConfig testCaseConfigs [] =
1011 {
1012 // minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0
1013 { "equal_min_3_max_3",3.0f, 3.0f, 0.0f, 0.0f },
1014 // minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0
1015 { "select_min_1",1.0f, 5.0f, 0.0f, 0.0f },
1016 // minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5
1017 { "select_max_4",0.0f, 4.0f, 0.0f, 5.0f },
1018 // minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0
1019 { "select_bias_2_1",0.0f, 2.1f, 5.0f, 0.0f },
1020 // minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0
1021 { "select_bias_2_5",0.0f, 5.0f, 2.5f, 0.00001f },
1022 // minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0
1023 { "select_bias_3_1",0.0f, 5.0f, -0.9f, 4.0f },
1024 // minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7
1025 { "select_bias_3_7",0.0f, 5.0f, 3.0f, 0.7f },
1026 };
1027
1028 MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD"));
1029
1030 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1031 {
1032 const TestCaseConfig& config = testCaseConfigs[configNdx];
1033
1034 samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, pipelineConstructionType, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod, separateStencilUsage));
1035 }
1036
1037 return samplerLodTests;
1038 }
1039
createSamplerMipmapTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)1040 MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
1041 {
1042 MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes"));
1043
1044 // Mipmap mode: nearest
1045 MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST"));
1046 mipmapNearestTests->addChild(createSamplerLodTests(testCtx, pipelineConstructionType, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST, separateStencilUsage).release());
1047 samplerMipmapTests->addChild(mipmapNearestTests.release());
1048
1049 // Mipmap mode: linear
1050 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
1051 {
1052 MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR"));
1053 mipmapLinearTests->addChild(createSamplerLodTests(testCtx, pipelineConstructionType, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR, separateStencilUsage).release());
1054 samplerMipmapTests->addChild(mipmapLinearTests.release());
1055 }
1056
1057 return samplerMipmapTests;
1058 }
1059
getAddressModesCaseName(VkSamplerAddressMode u,VkSamplerAddressMode v,VkSamplerAddressMode w,BorderColor border,tcu::IVec4 customIntValue,bool formatless,bool sampleStencil)1060 std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border, tcu::IVec4 customIntValue, bool formatless, bool sampleStencil)
1061 {
1062 static const char* borderColorNames[BORDER_COLOR_COUNT] =
1063 {
1064 "opaque_black",
1065 "opaque_white",
1066 "transparent_black",
1067 "custom"
1068 };
1069
1070 std::ostringstream caseName;
1071
1072 if (u == v && v == w)
1073 {
1074 const std::string fullName = getSamplerAddressModeName(u);
1075 DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
1076
1077 caseName << "all_";
1078 caseName << de::toLower(fullName.substr(19));
1079
1080 if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
1081 {
1082 caseName << "_" << borderColorNames[border];
1083 }
1084 }
1085 else
1086 {
1087 const std::string fullNameU = getSamplerAddressModeName(u);
1088 const std::string fullNameV = getSamplerAddressModeName(v);
1089 const std::string fullNameW = getSamplerAddressModeName(w);
1090
1091 DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
1092 DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
1093 DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
1094
1095 caseName << "uvw"
1096 << "_" << de::toLower(fullNameU.substr(19))
1097 << "_" << de::toLower(fullNameV.substr(19))
1098 << "_" << de::toLower(fullNameW.substr(19));
1099 }
1100
1101 if (border == BORDER_COLOR_CUSTOM)
1102 {
1103 caseName << "_";
1104 for (int i = 0; i < 4; i++)
1105 caseName << customIntValue[i];
1106
1107 if (formatless)
1108 caseName << "_formatless";
1109
1110 }
1111
1112 if (sampleStencil)
1113 caseName << "_stencil";
1114
1115 return caseName.str();
1116 }
1117
createSamplerAddressModesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)1118 MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
1119 {
1120 struct TestCaseConfig
1121 {
1122 TestCaseConfig (VkSamplerAddressMode _u,
1123 VkSamplerAddressMode _v,
1124 VkSamplerAddressMode _w,
1125 BorderColor _border,
1126 bool _customColorFormatless = false,
1127 tcu::Vec4 _customColorValueFloat = tcu::Vec4(),
1128 tcu::IVec4 _customColorValueInt = tcu::IVec4())
1129 : u(_u), v(_v), w(_w), border(_border), customColorFormatless(_customColorFormatless)
1130 , customColorValueFloat(_customColorValueFloat), customColorValueInt(_customColorValueInt)
1131 {
1132
1133 }
1134
1135 VkSamplerAddressMode u;
1136 VkSamplerAddressMode v;
1137 VkSamplerAddressMode w;
1138 BorderColor border;
1139 bool customColorFormatless;
1140 tcu::Vec4 customColorValueFloat;
1141 tcu::IVec4 customColorValueInt;
1142 };
1143
1144 const TestCaseConfig testCaseConfigs[] =
1145 {
1146 // All address modes equal
1147 { 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 },
1148 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
1149 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
1150 { 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 },
1151
1152 // All address modes equal using border color
1153 { 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 },
1154 { 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 },
1155 { 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 },
1156
1157 // Pairwise combinations of address modes not covered by previous tests
1158 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1159 { 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 },
1160 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1161 { 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 },
1162 { 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 },
1163 { 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 },
1164 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1165 { 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 },
1166 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1167 { 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 },
1168 { 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 },
1169 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1170 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1171 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1172 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
1173 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1174 { 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 },
1175 { 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 },
1176 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
1177 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1178 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
1179 { 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 },
1180
1181 // Custom border color tests
1182 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1183 false, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::IVec4(0, 0, 0, 0) },
1184 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1185 false, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(0, 0, 1, 1) },
1186 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1187 false, tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::IVec4(1, 0, 0, 0) },
1188 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1189 false, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::IVec4(1, 0, 0, 1) },
1190 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1191 false, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(1, 0, 1, 1) },
1192 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1193 false, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::IVec4(1, 1, 0, 1) },
1194
1195 // Custom border color formatless
1196 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1197 true, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::IVec4(1, 0, 1, 1) },
1198 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM,
1199 true, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::IVec4(1, 1, 0, 1) },
1200 };
1201
1202 MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes"));
1203
1204 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1205 {
1206 const TestCaseConfig& config = testCaseConfigs[configNdx];
1207
1208 if (!imageViewType.isNormalized() &&
1209 ((config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
1210 (config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)))
1211 continue;
1212
1213 // VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_B5G5R5A1_UNORM_PACK16
1214 // and VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR are forbidden for non-formatless custom border color.
1215 if ((imageFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1216 imageFormat == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1217 #ifndef CTS_USES_VULKANSC
1218 imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR ||
1219 #endif
1220 imageFormat == VK_FORMAT_B5G5R5A1_UNORM_PACK16) && config.border == BORDER_COLOR_CUSTOM && config.customColorFormatless)
1221 continue;
1222
1223 for (int i = 0; i < 2; ++i)
1224 {
1225 const bool isDSFormat = isDepthStencilFormat(imageFormat);
1226 const bool sampleStencil = (i > 0);
1227
1228 if (separateStencilUsage && sampleStencil)
1229 continue;
1230
1231 if (!isDSFormat && sampleStencil)
1232 continue;
1233
1234 if (isDSFormat)
1235 {
1236 const auto tcuFormat = mapVkFormat(imageFormat);
1237
1238 if (!sampleStencil && !tcu::hasDepthComponent(tcuFormat.order))
1239 continue;
1240 if (sampleStencil && !tcu::hasStencilComponent(tcuFormat.order))
1241 continue;
1242 }
1243
1244 samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx,
1245 getAddressModesCaseName(config.u, config.v, config.w, config.border, config.customColorValueInt, config.customColorFormatless, sampleStencil).c_str(),
1246 pipelineConstructionType,
1247 imageViewType,
1248 imageFormat,
1249 config.u, config.v, config.w,
1250 getFormatBorderColor(config.border, imageFormat, sampleStencil),
1251 getFormatCustomBorderColor(config.customColorValueFloat, config.customColorValueInt, imageFormat, sampleStencil),
1252 config.customColorFormatless,
1253 separateStencilUsage,
1254 sampleStencil));
1255 }
1256 }
1257
1258 return samplerAddressModesTests;
1259 }
1260
1261 // Exact sampling case:
1262 // 1) Create a texture and a framebuffer image of the same size.
1263 // 2) Draw a full screen quad with the texture and VK_FILTER_NEAREST.
1264 // 3) Verify the rendered image matches the texture exactly.
1265 class ExactSamplingCase : public vkt::TestCase
1266 {
1267 public:
1268 struct Params
1269 {
1270 PipelineConstructionType pipelineConstructionType;
1271 vk::VkFormat format;
1272 bool unnormalizedCoordinates;
1273 bool solidColor;
1274 tcu::Maybe<float> offsetSign; // -1.0 or 1.0
1275 };
1276
1277 struct PushConstants
1278 {
1279 float texWidth;
1280 float texHeight;
1281 };
1282
1283 struct VertexData
1284 {
1285 tcu::Vec2 vtxCoords;
1286 tcu::Vec2 texCoords;
1287
1288 static vk::VkVertexInputBindingDescription getBindingDescription (void);
1289 static std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions (void);
1290 };
1291
1292 ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const Params& params);
~ExactSamplingCase(void)1293 virtual ~ExactSamplingCase (void) {}
1294
1295 virtual void initPrograms (vk::SourceCollections& programCollection) const;
1296 virtual TestInstance* createInstance (Context& context) const;
1297 virtual void checkSupport (Context& context) const;
1298
1299 private:
1300 Params m_params;
1301 };
1302
1303 class ExactSamplingInstance : public vkt::TestInstance
1304 {
1305 public:
1306 using Params = ExactSamplingCase::Params;
1307
1308 ExactSamplingInstance (Context& context, const Params& params);
~ExactSamplingInstance(void)1309 virtual ~ExactSamplingInstance (void) {}
1310
1311 virtual tcu::TestStatus iterate (void);
1312
1313 vk::VkExtent3D getTextureExtent (void) const;
1314
1315 private:
1316 Params m_params;
1317 };
1318
getBindingDescription(void)1319 vk::VkVertexInputBindingDescription ExactSamplingCase::VertexData::getBindingDescription (void)
1320 {
1321 static const vk::VkVertexInputBindingDescription desc =
1322 {
1323 0u, // deUint32 binding;
1324 static_cast<deUint32>(sizeof(ExactSamplingCase::VertexData)), // deUint32 stride;
1325 vk::VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
1326 };
1327
1328 return desc;
1329 }
1330
getAttributeDescriptions(void)1331 std::vector<vk::VkVertexInputAttributeDescription> ExactSamplingCase::VertexData::getAttributeDescriptions (void)
1332 {
1333 static const std::vector<vk::VkVertexInputAttributeDescription> desc =
1334 {
1335 {
1336 0u, // deUint32 location;
1337 0u, // deUint32 binding;
1338 vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1339 static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, vtxCoords)), // deUint32 offset;
1340 },
1341 {
1342 1u, // deUint32 location;
1343 0u, // deUint32 binding;
1344 vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1345 static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, texCoords)), // deUint32 offset;
1346 },
1347 };
1348
1349 return desc;
1350 }
1351
1352
ExactSamplingCase(tcu::TestContext & testCtx,const std::string & name,const Params & params)1353 ExactSamplingCase::ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const Params& params)
1354 : vkt::TestCase{testCtx, name}, m_params(params)
1355 {
1356 }
1357
initPrograms(vk::SourceCollections & programCollection) const1358 void ExactSamplingCase::initPrograms (vk::SourceCollections& programCollection) const
1359 {
1360 std::ostringstream vertexShader;
1361
1362 std::string texCoordX = "inTexCoord.x";
1363 std::string texCoordY = "inTexCoord.y";
1364
1365 if (m_params.unnormalizedCoordinates)
1366 {
1367 texCoordX += " * pushc.texWidth";
1368 texCoordY += " * pushc.texHeight";
1369 }
1370
1371 vertexShader
1372 << "#version 450\n"
1373 << "\n"
1374 << "layout(push_constant, std430) uniform PushConstants\n"
1375 << "{\n"
1376 << " float texWidth;\n"
1377 << " float texHeight;\n"
1378 << "} pushc;\n"
1379 << "\n"
1380 << "layout(location = 0) in vec2 inPosition;\n"
1381 << "layout(location = 1) in vec2 inTexCoord;\n"
1382 << "\n"
1383 << "layout(location = 0) out vec2 fragTexCoord;\n"
1384 << "\n"
1385 << "void main() {\n"
1386 << " gl_Position = vec4(inPosition, 0.0, 1.0);\n"
1387 << " fragTexCoord = vec2(" << texCoordX << ", " << texCoordY << ");\n"
1388 << "}\n"
1389 ;
1390
1391 programCollection.glslSources.add("vert") << glu::VertexSource{vertexShader.str()};
1392
1393 std::ostringstream fragmentShader;
1394
1395 std::string typePrefix;
1396 if (vk::isIntFormat(m_params.format))
1397 typePrefix = "i";
1398 else if (vk::isUintFormat(m_params.format))
1399 typePrefix = "u";
1400
1401 const std::string samplerType = typePrefix + "sampler2D";
1402 const std::string colorType = typePrefix + "vec4";
1403
1404 fragmentShader
1405 << "#version 450\n"
1406 << "\n"
1407 << "layout(set = 0, binding = 0) uniform " << samplerType << " texSampler;\n"
1408 << "\n"
1409 << "layout(location = 0) in vec2 fragTexCoord;\n"
1410 << "\n"
1411 << "layout(location = 0) out " << colorType << " outColor;\n"
1412 << "\n"
1413 << "void main() {\n";
1414
1415 if (m_params.unnormalizedCoordinates)
1416 {
1417 fragmentShader << " outColor = textureLod(texSampler, fragTexCoord, 0.0f);";
1418 }
1419 else
1420 {
1421 fragmentShader << " outColor = texture(texSampler, fragTexCoord);\n";
1422 }
1423
1424 fragmentShader << "}\n";
1425
1426 programCollection.glslSources.add("frag") << glu::FragmentSource{fragmentShader.str()};
1427 }
1428
createInstance(Context & context) const1429 TestInstance* ExactSamplingCase::createInstance (Context& context) const
1430 {
1431 return new ExactSamplingInstance{context, m_params};
1432 }
1433
checkSupport(Context & context) const1434 void ExactSamplingCase::checkSupport (Context& context) const
1435 {
1436 #ifndef CTS_USES_VULKANSC
1437 if (m_params.format == VK_FORMAT_A8_UNORM_KHR)
1438 context.requireDeviceFunctionality("VK_KHR_maintenance5");
1439 #endif // CTS_USES_VULKANSC
1440
1441 const auto& vki = context.getInstanceInterface();
1442 const auto physicalDevice = context.getPhysicalDevice();
1443 const auto props = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, m_params.format);
1444 const vk::VkFormatFeatureFlags requiredFeatures =
1445 (vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT
1446 |vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
1447 |vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
1448 |vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
1449 |(m_params.solidColor ? vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT : 0)
1450 );
1451
1452 checkPipelineConstructionRequirements(vki, physicalDevice, m_params.pipelineConstructionType);
1453
1454 if ((props.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
1455 TCU_THROW(NotSupportedError, "Selected format does not support the required features");
1456 }
1457
ExactSamplingInstance(Context & context,const Params & params)1458 ExactSamplingInstance::ExactSamplingInstance (Context& context, const Params& params)
1459 : vkt::TestInstance{context}, m_params(params)
1460 {
1461 }
1462
getTextureExtent(void) const1463 vk::VkExtent3D ExactSamplingInstance::getTextureExtent (void) const
1464 {
1465 return vk::makeExtent3D(256u, 256u, 1u);
1466 }
1467
iterate(void)1468 tcu::TestStatus ExactSamplingInstance::iterate (void)
1469 {
1470 const auto& vki = m_context.getInstanceInterface();
1471 const auto& vkd = m_context.getDeviceInterface();
1472 const auto physDevice = m_context.getPhysicalDevice();
1473 const auto device = m_context.getDevice();
1474 auto& allocator = m_context.getDefaultAllocator();
1475 const auto queue = m_context.getUniversalQueue();
1476 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1477
1478 const auto tcuFormat = vk::mapVkFormat(m_params.format);
1479 const auto formatInfo = tcu::getTextureFormatInfo(tcuFormat);
1480 const auto texExtent = getTextureExtent();
1481 const auto texUsage = (vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT);
1482 const auto fbUsage = (vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
1483 const auto descType = vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1484 const auto texLayout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1485 const bool& unnorm = m_params.unnormalizedCoordinates;
1486
1487 // Some code below depends on this.
1488 DE_ASSERT(texExtent.depth == 1u);
1489
1490 const vk::VkImageCreateInfo texImgCreateInfo =
1491 {
1492 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1493 nullptr, // const void* pNext;
1494 0u, // VkImageCreateFlags flags;
1495 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1496 m_params.format, // VkFormat format;
1497 texExtent, // VkExtent3D extent;
1498 1u, // deUint32 mipLevels;
1499 1u, // deUint32 arrayLayers;
1500 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1501 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1502 texUsage, // VkImageUsageFlags usage;
1503 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1504 1u, // deUint32 queueFamilyIndexCount;
1505 &queueIndex, // const deUint32* pQueueFamilyIndices;
1506 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1507 };
1508
1509 const vk::VkImageCreateInfo fbImgCreateInfo =
1510 {
1511 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1512 nullptr, // const void* pNext;
1513 0u, // VkImageCreateFlags flags;
1514 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1515 m_params.format, // VkFormat format;
1516 texExtent, // VkExtent3D extent;
1517 1u, // deUint32 mipLevels;
1518 1u, // deUint32 arrayLayers;
1519 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1520 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1521 fbUsage, // VkImageUsageFlags usage;
1522 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1523 1u, // deUint32 queueFamilyIndexCount;
1524 &queueIndex, // const deUint32* pQueueFamilyIndices;
1525 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1526 };
1527
1528 // Create main and framebuffer images.
1529 const vk::ImageWithMemory texImage {vkd, device, allocator, texImgCreateInfo, vk::MemoryRequirement::Any};
1530 const vk::ImageWithMemory fbImage {vkd, device, allocator, fbImgCreateInfo, vk::MemoryRequirement::Any};
1531
1532 // Corresponding image views.
1533 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1534 const auto texView = vk::makeImageView(vkd, device, texImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
1535 const auto fbView = vk::makeImageView(vkd, device, fbImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
1536
1537 // Buffers to create the texture and verify results.
1538 const vk::VkDeviceSize texBufferSize = static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * texExtent.width * texExtent.height * texExtent.depth);
1539 const auto texBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1540 const auto resultsBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1541 const vk::BufferWithMemory texBuffer {vkd, device, allocator, texBufferInfo, vk::MemoryRequirement::HostVisible};
1542 const vk::BufferWithMemory resultsBuffer {vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible};
1543
1544 // Create texture.
1545 const tcu::IVec2 iImgSize {static_cast<int>(texExtent.width), static_cast<int>(texExtent.height)};
1546 auto& texBufferAlloc = texBuffer.getAllocation();
1547 auto texBufferPtr = reinterpret_cast<char*>(texBufferAlloc.getHostPtr()) + texBufferAlloc.getOffset();
1548 const tcu::PixelBufferAccess texPixels {tcuFormat, iImgSize[0], iImgSize[1], 1, texBufferPtr};
1549
1550 const int W = texPixels.getWidth();
1551 const int H = texPixels.getHeight();
1552 const int D = texPixels.getDepth();
1553
1554 const float divX = static_cast<float>(W - 1);
1555 const float divY = static_cast<float>(H - 1);
1556
1557 tcu::Vec4 texColor;
1558
1559 for (int x = 0; x < W; ++x)
1560 for (int y = 0; y < H; ++y)
1561 for (int z = 0; z < D; ++z)
1562 {
1563 if (m_params.solidColor)
1564 {
1565 // Texture with solid color for filtered sampling.
1566 texColor = tcu::Vec4{0.5f, 0.25f, 0.7529411764705882f, 1.0f};
1567 }
1568 else
1569 {
1570 // Use a color gradient otherwise.
1571 const float colorX = static_cast<float>(x) / divX;
1572 const float colorY = static_cast<float>(y) / divY;
1573 const float colorZ = std::min(colorX, colorY);
1574
1575 texColor = tcu::Vec4{colorX, colorY, colorZ, 1.0f};
1576 }
1577 const tcu::Vec4 finalColor = (texColor - formatInfo.lookupBias) / formatInfo.lookupScale;
1578 texPixels.setPixel(finalColor, x, y, z);
1579 }
1580
1581 vk::flushAlloc(vkd, device, texBufferAlloc);
1582
1583 float minU = 0.0f;
1584 float maxU = 1.0f;
1585 float minV = 0.0f;
1586 float maxV = 1.0f;
1587
1588 // When testing the edges, apply a texture offset of almost half a texel, so the sample location is very close to the texel border.
1589 if (m_params.offsetSign)
1590 {
1591 const float sign = m_params.offsetSign.get(); DE_ASSERT(sign == 1.0f || sign == -1.0f);
1592 const float offsetWidth = 0.499f / static_cast<float>(texExtent.width);
1593 const float offsetHeight = 0.499f / static_cast<float>(texExtent.height);
1594
1595 minU += sign * offsetWidth;
1596 maxU += sign * offsetWidth;
1597 minV += sign * offsetHeight;
1598 maxV += sign * offsetHeight;
1599 }
1600
1601 const std::vector<ExactSamplingCase::VertexData> fullScreenQuad =
1602 {
1603 {{ 1.f, -1.f }, { maxU, minV }, },
1604 {{ -1.f, -1.f }, { minU, minV }, },
1605 {{ -1.f, 1.f }, { minU, maxV }, },
1606 {{ -1.f, 1.f }, { minU, maxV }, },
1607 {{ 1.f, -1.f }, { maxU, minV }, },
1608 {{ 1.f, 1.f }, { maxU, maxV }, },
1609 };
1610
1611 // Vertex buffer.
1612 const vk::VkDeviceSize vertexBufferSize = static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
1613 const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1614 const vk::BufferWithMemory vertexBuffer {vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible};
1615
1616 // Copy data to vertex buffer.
1617 const auto& vertexAlloc = vertexBuffer.getAllocation();
1618 const auto vertexDataPtr = reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
1619 deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
1620 vk::flushAlloc(vkd, device, vertexAlloc);
1621
1622 // Descriptor set layout.
1623 vk::DescriptorSetLayoutBuilder layoutBuilder;
1624 layoutBuilder.addSingleBinding(descType, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1625 const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1626
1627 // Descriptor pool.
1628 vk::DescriptorPoolBuilder poolBuilder;
1629 poolBuilder.addType(descType);
1630 const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1631
1632 // Descriptor set.
1633 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1634
1635 // Texture sampler. When using a solid color, test linear filtering. Linear filtering may incur in a small precission loss, but
1636 // it should be minimal and we should get the same color when converting back to the original format.
1637 const auto minMagFilter = (m_params.solidColor ? vk::VK_FILTER_LINEAR : vk::VK_FILTER_NEAREST);
1638 const auto addressMode = (unnorm ? vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : vk::VK_SAMPLER_ADDRESS_MODE_REPEAT);
1639 const auto unnormalizedCoordinates = (unnorm ? VK_TRUE : VK_FALSE);
1640
1641 const vk::VkSamplerCreateInfo samplerCreateInfo =
1642 {
1643 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
1644 nullptr, // const void* pNext;
1645 0u, // VkSamplerCreateFlags flags;
1646 minMagFilter, // VkFilter magFilter;
1647 minMagFilter, // VkFilter minFilter;
1648 vk::VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
1649 addressMode, // VkSamplerAddressMode addressModeU;
1650 addressMode, // VkSamplerAddressMode addressModeV;
1651 addressMode, // VkSamplerAddressMode addressModeW;
1652 0.0f, // float mipLodBias;
1653 VK_FALSE, // VkBool32 anisotropyEnable;
1654 1.0f, // float maxAnisotropy;
1655 VK_FALSE, // VkBool32 compareEnable;
1656 vk::VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1657 0.0f, // float minLod;
1658 0.0f, // float maxLod;
1659 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
1660 unnormalizedCoordinates, // VkBool32 unnormalizedCoordinates;
1661 };
1662 const auto texSampler = vk::createSampler(vkd, device, &samplerCreateInfo);
1663
1664 // Update descriptor set with the descriptor.
1665 vk::DescriptorSetUpdateBuilder updateBuilder;
1666 const auto descriptorImageInfo = vk::makeDescriptorImageInfo(texSampler.get(), texView.get(), texLayout);
1667 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), descType, &descriptorImageInfo);
1668 updateBuilder.update(vkd, device);
1669
1670 // Shader modules.
1671 const auto vertexModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1672 const auto fragModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1673
1674 // Render pass.
1675 const vk::VkAttachmentDescription fbAttachment =
1676 {
1677 0u, // VkAttachmentDescriptionFlags flags;
1678 m_params.format, // VkFormat format;
1679 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1680 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1681 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1682 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1683 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1684 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1685 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1686 };
1687
1688 const vk::VkAttachmentReference colorRef =
1689 {
1690 0u, // deUint32 attachment;
1691 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1692 };
1693
1694 const vk::VkSubpassDescription subpass =
1695 {
1696 0u, // VkSubpassDescriptionFlags flags;
1697 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1698 0u, // deUint32 inputAttachmentCount;
1699 nullptr, // const VkAttachmentReference* pInputAttachments;
1700 1u, // deUint32 colorAttachmentCount;
1701 &colorRef, // const VkAttachmentReference* pColorAttachments;
1702 0u, // const VkAttachmentReference* pResolveAttachments;
1703 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
1704 0u, // deUint32 preserveAttachmentCount;
1705 nullptr, // const deUint32* pPreserveAttachments;
1706 };
1707
1708 const vk::VkRenderPassCreateInfo renderPassInfo =
1709 {
1710 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1711 nullptr, // const void* pNext;
1712 0u, // VkRenderPassCreateFlags flags;
1713 1u, // deUint32 attachmentCount;
1714 &fbAttachment, // const VkAttachmentDescription* pAttachments;
1715 1u, // deUint32 subpassCount;
1716 &subpass, // const VkSubpassDescription* pSubpasses;
1717 0u, // deUint32 dependencyCount;
1718 nullptr, // const VkSubpassDependency* pDependencies;
1719 };
1720 RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, &renderPassInfo);
1721
1722 // Framebuffer.
1723 std::vector<vk::VkImageView> attachments;
1724 attachments.push_back(fbView.get());
1725 renderPass.createFramebuffer(vkd, device, 1u, &fbImage.get(),&fbView.get(), texExtent.width, texExtent.height, texExtent.depth);
1726
1727 // Push constant range.
1728 const vk::VkPushConstantRange pcRange =
1729 {
1730 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags stageFlags;
1731 0u, // deUint32 offset;
1732 static_cast<deUint32>(sizeof(ExactSamplingCase::PushConstants)), // deUint32 size;
1733 };
1734
1735 // Pipeline layout.
1736 const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo =
1737 {
1738 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1739 nullptr, // const void* pNext;
1740 0u, // VkPipelineLayoutCreateFlags flags;
1741 1u, // deUint32 setLayoutCount;
1742 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
1743 1u, // deUint32 pushConstantRangeCount;
1744 &pcRange, // const VkPushConstantRange* pPushConstantRanges;
1745 };
1746 const vk::PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vkd, device, &pipelineLayoutInfo);
1747
1748 // Graphics pipeline.
1749 const std::vector<vk::VkViewport> viewports { vk::makeViewport(texExtent) };
1750 const vk::VkRect2D renderArea = vk::makeRect2D(texExtent);
1751 const std::vector<vk::VkRect2D> scissors { renderArea };
1752
1753 const auto vtxBindingDescription = ExactSamplingCase::VertexData::getBindingDescription();
1754 const auto vtxAttributeDescriptions = ExactSamplingCase::VertexData::getAttributeDescriptions();
1755
1756 const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
1757 {
1758 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
1759 nullptr, // const void* pNext
1760 0u, // VkPipelineVertexInputStateCreateFlags flags
1761 1u, // deUint32 vertexBindingDescriptionCount
1762 &vtxBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
1763 static_cast<deUint32>(vtxAttributeDescriptions.size()), // deUint32 vertexAttributeDescriptionCount
1764 vtxAttributeDescriptions.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
1765 };
1766
1767 GraphicsPipelineWrapper pipeline(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
1768 pipeline.setDefaultDepthStencilState()
1769 .setDefaultRasterizationState()
1770 .setDefaultMultisampleState()
1771 .setDefaultColorBlendState()
1772 .setupVertexInputState(&vertexInputInfo)
1773 .setupPreRasterizationShaderState(viewports,
1774 scissors,
1775 pipelineLayout,
1776 *renderPass,
1777 0u,
1778 vertexModule)
1779 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1780 .setupFragmentOutputState(*renderPass)
1781 .setMonolithicPipelineLayout(pipelineLayout)
1782 .buildPipeline();
1783
1784 // Command pool and command buffer.
1785 const auto cmdPool = vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
1786 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1787 const auto cmdBuffer = cmdBufferPtr.get();
1788
1789 // Draw quad.
1790 const ExactSamplingCase::PushConstants pushConstants =
1791 {
1792 static_cast<float>(texExtent.width),
1793 static_cast<float>(texExtent.height),
1794 };
1795
1796 const tcu::Vec4 clearFbColor (0.0f, 0.0f, 0.0f, 1.0f);
1797 const vk::VkDeviceSize vertexBufferOffset = 0ull;
1798
1799 const auto vertexBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
1800 const auto preBufferCopyBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, texBuffer.get(), 0ull, texBufferSize);
1801 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);
1802 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);
1803 const auto texCopyRange = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1804 const auto texImageCopy = vk::makeBufferImageCopy(texExtent, texCopyRange);
1805
1806 vk::beginCommandBuffer(vkd, cmdBuffer);
1807
1808 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vertexBufferBarrier, 0u, nullptr);
1809 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 1u, &preBufferCopyBarrier, 0u, nullptr);
1810 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preTexCopyBarrier);
1811 vkd.cmdCopyBufferToImage(cmdBuffer, texBuffer.get(), texImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &texImageCopy);
1812 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postTexCopyBarrier);
1813
1814 renderPass.begin(vkd, cmdBuffer, renderArea, clearFbColor);
1815 pipeline.bind(cmdBuffer);
1816 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1817 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1818 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
1819 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
1820 renderPass.end(vkd, cmdBuffer);
1821
1822 vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), iImgSize);
1823
1824 vk::endCommandBuffer(vkd, cmdBuffer);
1825 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1826
1827 // Check results.
1828 const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
1829 vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
1830
1831 const auto resultsBufferPtr = reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
1832 const tcu::ConstPixelBufferAccess resultPixels {tcuFormat, iImgSize[0], iImgSize[1], 1, resultsBufferPtr};
1833
1834 const tcu::TextureFormat diffFormat {tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
1835 const auto diffBytes = tcu::getPixelSize(diffFormat) * iImgSize[0] * iImgSize[1];
1836 std::unique_ptr<deUint8[]> diffData {new deUint8[diffBytes]};
1837 const tcu::PixelBufferAccess diffImg {diffFormat, iImgSize[0], iImgSize[1], 1, diffData.get()};
1838
1839 const tcu::Vec4 colorRed {1.0f, 0.0f, 0.0f, 1.0f};
1840 const tcu::Vec4 colorGreen {0.0f, 1.0f, 0.0f, 1.0f};
1841
1842 // Clear diff image.
1843 deMemset(diffData.get(), 0, static_cast<size_t>(diffBytes));
1844
1845 bool pass = true;
1846 for (int x = 0; x < W; ++x)
1847 for (int y = 0; y < H; ++y)
1848 for (int z = 0; z < D; ++z)
1849 {
1850 const auto inPix = texPixels.getPixel(x, y, z);
1851 const auto outPix = resultPixels.getPixel(x, y, z);
1852 if (inPix == outPix)
1853 {
1854 diffImg.setPixel(colorGreen, x, y, z);
1855 }
1856 else
1857 {
1858 pass = false;
1859 diffImg.setPixel(colorRed, x, y, z);
1860 }
1861 }
1862
1863 tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1864 if (!pass)
1865 {
1866 auto& log = m_context.getTestContext().getLog();
1867 log << tcu::TestLog::Image("input", "Input texture", texPixels);
1868 log << tcu::TestLog::Image("output", "Rendered image", resultPixels);
1869 log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffImg);
1870 status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
1871 }
1872
1873 return status;
1874 }
1875
1876 enum class LodBiasCase
1877 {
1878 SAMPLER_BIAS = 0,
1879 SAMPLER_MINLOD = 1,
1880 SHADER_LOD = 2,
1881 SHADER_BIAS = 3,
1882 VIEW_MINLOD = 4,
1883 CASE_COUNT = 5,
1884 };
1885
getLodBiasCaseName(LodBiasCase lodBiasCase)1886 std::string getLodBiasCaseName (LodBiasCase lodBiasCase)
1887 {
1888 std::string name;
1889
1890 switch (lodBiasCase)
1891 {
1892 case LodBiasCase::SAMPLER_BIAS: name = "sampler_bias"; break;
1893 case LodBiasCase::SAMPLER_MINLOD: name = "sampler_minlod"; break;
1894 case LodBiasCase::SHADER_LOD: name = "shader_lod"; break;
1895 case LodBiasCase::SHADER_BIAS: name = "shader_bias"; break;
1896 case LodBiasCase::VIEW_MINLOD: name = "view_minlod"; break;
1897 case LodBiasCase::CASE_COUNT: // fallthrough
1898 default:
1899 DE_ASSERT(false);
1900 break;
1901 }
1902
1903 return name;
1904 }
1905
1906 struct MaxSamplerLodBiasParams
1907 {
1908 const PipelineConstructionType pipelineConstructionType;
1909 const LodBiasCase lodBiasCase;
1910 };
1911
1912 class MaxSamplerLodBiasCase : public vkt::TestCase
1913 {
1914 public:
MaxSamplerLodBiasCase(tcu::TestContext & testCtx,const std::string & name,const MaxSamplerLodBiasParams & params)1915 MaxSamplerLodBiasCase (tcu::TestContext& testCtx, const std::string& name, const MaxSamplerLodBiasParams& params)
1916 : vkt::TestCase (testCtx, name)
1917 , m_params (params)
1918 {}
~MaxSamplerLodBiasCase(void)1919 virtual ~MaxSamplerLodBiasCase (void) {}
1920
1921 void checkSupport (Context& context) const override;
1922 void initPrograms (vk::SourceCollections& programCollection) const override;
1923 TestInstance* createInstance (Context& context) const override;
1924
1925 protected:
1926 const MaxSamplerLodBiasParams m_params;
1927 };
1928
1929 class MaxSamplerLodBiasInstance : public vkt::TestInstance
1930 {
1931 public:
MaxSamplerLodBiasInstance(Context & context,const MaxSamplerLodBiasParams & params)1932 MaxSamplerLodBiasInstance (Context& context, const MaxSamplerLodBiasParams& params)
1933 : vkt::TestInstance (context)
1934 , m_params (params)
1935 {}
~MaxSamplerLodBiasInstance(void)1936 virtual ~MaxSamplerLodBiasInstance (void) {}
1937
1938 tcu::TestStatus iterate (void);
1939
1940 protected:
1941 const MaxSamplerLodBiasParams m_params;
1942 };
1943
checkSupport(Context & context) const1944 void MaxSamplerLodBiasCase::checkSupport (Context& context) const
1945 {
1946 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1947
1948 if (m_params.lodBiasCase == LodBiasCase::VIEW_MINLOD)
1949 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
1950 }
1951
initPrograms(vk::SourceCollections & programCollection) const1952 void MaxSamplerLodBiasCase::initPrograms (vk::SourceCollections& programCollection) const
1953 {
1954 std::ostringstream vert;
1955 vert
1956 << "#version 460\n"
1957 << "layout (location=0) in vec4 inPos;\n"
1958 << "void main (void) {\n"
1959 << " gl_Position = inPos;\n"
1960 << "}\n"
1961 ;
1962 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1963
1964 std::string sampleStatement;
1965 const std::string sampleCoords = "vec2(gl_FragCoord.x / pc.fbWidth, gl_FragCoord.y / pc.fbHeight)";
1966
1967 if (m_params.lodBiasCase == LodBiasCase::SHADER_LOD)
1968 sampleStatement = "textureLod(texSampler, " + sampleCoords + ", pc.lodLevel)";
1969 else if (m_params.lodBiasCase == LodBiasCase::SHADER_BIAS)
1970 sampleStatement = "texture(texSampler, " + sampleCoords + ", pc.lodLevel)";
1971 else
1972 sampleStatement = "textureLod(texSampler, " + sampleCoords + ", 0.0)";
1973
1974 DE_ASSERT(!sampleStatement.empty());
1975
1976 std::ostringstream frag;
1977 frag
1978 << "#version 460\n"
1979 << "layout (location=0) out vec4 outColor;\n"
1980 << "layout (set=0, binding=0) uniform sampler2D texSampler;\n"
1981 << "layout (push_constant, std430) uniform PushConstantBlock {\n"
1982 << " float lodLevel;\n"
1983 << " float fbWidth;\n"
1984 << " float fbHeight;\n"
1985 << "} pc;\n"
1986 << "void main (void) {\n"
1987 << " outColor = " << sampleStatement << ";\n"
1988 << "}\n"
1989 ;
1990 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1991 }
1992
createInstance(Context & context) const1993 TestInstance* MaxSamplerLodBiasCase::createInstance (Context& context) const
1994 {
1995 return new MaxSamplerLodBiasInstance(context, m_params);
1996 }
1997
iterate(void)1998 tcu::TestStatus MaxSamplerLodBiasInstance::iterate (void)
1999 {
2000 const auto ctx = m_context.getContextCommonData();
2001 const auto vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
2002 const auto tcuFormat = mapVkFormat(vkFormat);
2003 const auto imageType = VK_IMAGE_TYPE_2D;
2004 const auto tiling = VK_IMAGE_TILING_OPTIMAL;
2005 const auto textureUsage = (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
2006 const auto fbUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2007 const auto sampleCount = VK_SAMPLE_COUNT_1_BIT;
2008 const auto descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
2009 const auto maxLodBias = getPhysicalDeviceProperties(ctx.vki, ctx.physicalDevice).limits.maxSamplerLodBias;
2010 const auto roundedBias = deFloatFloor(maxLodBias + 0.5f);
2011 const auto textureProperties = getPhysicalDeviceImageFormatProperties(ctx.vki, ctx.physicalDevice, vkFormat, imageType, tiling, textureUsage, 0u);
2012 const auto textureExtent = makeExtent3D(textureProperties.maxExtent.width, 1u, 1u);
2013 const auto fbExtent = tcu::IVec3(1, 1, 1);
2014 const auto vkExtent = makeExtent3D(fbExtent);
2015 const auto baseSeed = 1687852938u;
2016
2017 const VkImageCreateInfo textureCreateInfo =
2018 {
2019 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2020 nullptr, // const void* pNext;
2021 0u, // VkImageCreateFlags flags;
2022 imageType, // VkImageType imageType;
2023 vkFormat, // VkFormat format;
2024 textureExtent, // VkExtent3D extent;
2025 textureProperties.maxMipLevels, // uint32_t mipLevels;
2026 1u, // uint32_t arrayLayers;
2027 sampleCount, // VkSampleCountFlagBits samples;
2028 tiling, // VkImageTiling tiling;
2029 textureUsage, // VkImageUsageFlags usage;
2030 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2031 0u, // uint32_t queueFamilyIndexCount;
2032 nullptr, // const uint32_t* pQueueFamilyIndices;
2033 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2034 };
2035 ImageWithMemory texture (ctx.vkd, ctx.device, ctx.allocator, textureCreateInfo, MemoryRequirement::Any);
2036 const auto textureColorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, textureCreateInfo.mipLevels, 0u, 1u);
2037 const auto accessedLevel = std::min(roundedBias, static_cast<float>(textureCreateInfo.mipLevels - 1u));
2038
2039 #ifndef CTS_USES_VULKANSC
2040 std::unique_ptr<VkImageViewMinLodCreateInfoEXT> viewMinLodPtr;
2041 if (m_params.lodBiasCase == LodBiasCase::VIEW_MINLOD)
2042 {
2043 viewMinLodPtr.reset(new VkImageViewMinLodCreateInfoEXT{
2044 VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT,
2045 nullptr,
2046 accessedLevel, // VUID-VkImageViewMinLodCreateInfoEXT-minLod-06456 prevents us from using maxLodBias directly.
2047 });
2048 }
2049 #endif // CTS_USES_VULKANSC
2050
2051 const VkImageViewCreateInfo viewCreateInfo =
2052 {
2053 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2054 #ifndef CTS_USES_VULKANSC
2055 viewMinLodPtr.get(), // const void* pNext;
2056 #else
2057 nullptr, // const void* pNext;
2058 #endif // CTS_USES_VULKANSC
2059 0u, // VkImageViewCreateFlags flags;
2060 texture.get(), // VkImage image;
2061 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
2062 vkFormat, // VkFormat format;
2063 { // VkComponentMapping components;
2064 VK_COMPONENT_SWIZZLE_R,
2065 VK_COMPONENT_SWIZZLE_G,
2066 VK_COMPONENT_SWIZZLE_B,
2067 VK_COMPONENT_SWIZZLE_A,
2068 },
2069 textureColorSRR, // VkImageSubresourceRange subresourceRange;
2070 };
2071 const auto textureView = createImageView(ctx.vkd, ctx.device, &viewCreateInfo);
2072
2073 // Output color buffer.
2074 ImageWithBuffer colorBuffer (ctx.vkd, ctx.device, ctx.allocator, vkExtent, vkFormat, fbUsage, imageType);
2075
2076 // Texture sampler.
2077 const float samplerMipLodBias = ((m_params.lodBiasCase == LodBiasCase::SAMPLER_BIAS) ? maxLodBias : 0.0f);
2078 const float samplerMinLod = ((m_params.lodBiasCase == LodBiasCase::SAMPLER_MINLOD) ? maxLodBias : 0.0f);
2079 const VkSamplerCreateInfo samplerCreateInfo =
2080 {
2081 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
2082 nullptr, // const void* pNext;
2083 0u, // VkSamplerCreateFlags flags;
2084 VK_FILTER_NEAREST, // VkFilter magFilter;
2085 VK_FILTER_NEAREST, // VkFilter minFilter;
2086 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
2087 VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeU;
2088 VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeV;
2089 VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeW;
2090 samplerMipLodBias, // float mipLodBias;
2091 VK_FALSE, // VkBool32 anisotropyEnable;
2092 0.0f, // float maxAnisotropy;
2093 VK_FALSE, // VkBool32 compareEnable;
2094 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
2095 samplerMinLod, // float minLod;
2096 VK_LOD_CLAMP_NONE, // float maxLod;
2097 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
2098 VK_FALSE, // VkBool32 unnormalizedCoordinates;
2099 };
2100 const auto sampler = createSampler(ctx.vkd, ctx.device, &samplerCreateInfo);
2101
2102 // Vertex buffer.
2103 const std::vector<tcu::Vec4> vertices
2104 {
2105 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2106 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
2107 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
2108 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f),
2109 };
2110 const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
2111 const auto vertexBufferInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2112 BufferWithMemory vertexBuffer (ctx.vkd, ctx.device, ctx.allocator, vertexBufferInfo, MemoryRequirement::HostVisible);
2113 auto& vertexBufferAlloc = vertexBuffer.getAllocation();
2114 void* vertexBufferDataPtr = vertexBufferAlloc.getHostPtr();
2115 const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
2116
2117 deMemcpy(vertexBufferDataPtr, de::dataOrNull(vertices), de::dataSize(vertices));
2118 flushAlloc(ctx.vkd, ctx.device, vertexBufferAlloc);
2119
2120 // Render pass and framebuffer.
2121 auto renderPass = RenderPassWrapper(m_params.pipelineConstructionType, ctx.vkd, ctx.device, vkFormat);
2122 renderPass.createFramebuffer(ctx.vkd, ctx.device, colorBuffer.getImage(), colorBuffer.getImageView(), vkExtent.width, vkExtent.height);
2123
2124 // Push constants.
2125 const std::vector<float> pcValues { maxLodBias, static_cast<float>(vkExtent.width), static_cast<float>(vkExtent.height) };
2126 const auto pcSize = static_cast<uint32_t>(de::dataSize(pcValues));
2127 const auto pcStages = VK_SHADER_STAGE_FRAGMENT_BIT;
2128 const auto pcRange = makePushConstantRange(pcStages, 0u, pcSize);
2129
2130 // Descriptor pool and set.
2131 DescriptorSetLayoutBuilder setLayoutBuilder;
2132 setLayoutBuilder.addSingleBinding (descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT);
2133 const auto descriptorSetLayout = setLayoutBuilder.build(ctx.vkd, ctx.device);
2134 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, ctx.vkd, ctx.device, *descriptorSetLayout, &pcRange);
2135
2136 DescriptorPoolBuilder descriptorPoolBuilder;
2137 descriptorPoolBuilder.addType(descriptorType);
2138 const auto descriptorPool = descriptorPoolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2139 const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *descriptorSetLayout);
2140
2141 DescriptorSetUpdateBuilder setUpdateBuilder;
2142 const auto samplerDescriptorInfo = makeDescriptorImageInfo(*sampler, *textureView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2143 setUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &samplerDescriptorInfo);
2144 setUpdateBuilder.update(ctx.vkd, ctx.device);
2145
2146 // Pipeline.
2147 const auto& binaries = m_context.getBinaryCollection();
2148 const auto vertMod = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("vert"));
2149 const auto fragMod = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("frag"));
2150
2151 const std::vector<VkViewport> viewports (1u, makeViewport(vkExtent));
2152 const std::vector<VkRect2D> scissors (1u, makeRect2D(vkExtent));
2153
2154 GraphicsPipelineWrapper pipeline (ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
2155 pipeline.setDefaultDepthStencilState()
2156 .setDefaultRasterizationState()
2157 .setDefaultMultisampleState()
2158 .setDefaultColorBlendState()
2159 .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2160 .setupVertexInputState()
2161 .setupPreRasterizationShaderState(viewports,
2162 scissors,
2163 pipelineLayout,
2164 *renderPass,
2165 0u,
2166 vertMod)
2167 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragMod)
2168 .setupFragmentOutputState(*renderPass)
2169 .setMonolithicPipelineLayout(pipelineLayout)
2170 .buildPipeline();
2171
2172 CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
2173 const auto cmdBuffer = *cmd.cmdBuffer;
2174
2175 beginCommandBuffer(ctx.vkd, cmdBuffer);
2176
2177 // Transition texture to layout suitable for filling.
2178 const auto preFillBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), textureColorSRR);
2179 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preFillBarrier);
2180
2181 // Fill every level with a different random color.
2182 auto& log = m_context.getTestContext().getLog();
2183 de::Random rnd(baseSeed + static_cast<uint32_t>(m_params.lodBiasCase));
2184 std::vector<tcu::Vec4> levelColors;
2185 levelColors.reserve(textureCreateInfo.mipLevels);
2186
2187 for (uint32_t level = 0u; level < textureCreateInfo.mipLevels; ++level)
2188 {
2189 const auto levelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2190 // If we "embed" these expressions in the constructor below, separated by commas, the order in which colors are obtained would depend on the compiler.
2191 const auto red = rnd.getFloat(0.0f, 1.0f);
2192 const auto green = rnd.getFloat(0.0f, 1.0f);
2193 const auto blue = rnd.getFloat(0.0f, 1.0f);
2194 const tcu::Vec4 clearValue (red, green, blue, 1.0f);
2195 const auto clearValueColor = makeClearValueColorVec4(clearValue);
2196
2197 levelColors.push_back(clearValue);
2198 ctx.vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValueColor.color, 1u, &levelRange);
2199 log << tcu::TestLog::Message << "Level " << level << " cleared to " << clearValue << tcu::TestLog::EndMessage;
2200 }
2201
2202 // Transition texture to suitable layout for reading it in the shader.
2203 const auto preReadBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.get(), textureColorSRR);
2204 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, &preReadBarrier);
2205
2206 const tcu::Vec4 fbClearColor (0.0f, 0.0f, 0.0f, 0.0f);
2207 renderPass.begin(ctx.vkd, cmdBuffer, scissors.at(0u), fbClearColor);
2208 ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2209 pipeline.bind(cmdBuffer);
2210 ctx.vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2211 ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, pcStages, 0u, pcSize, de::dataOrNull(pcValues));
2212 ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
2213 renderPass.end(ctx.vkd, cmdBuffer);
2214
2215 // Copy color buffer to verification buffer.
2216 copyImageToBuffer(ctx.vkd,
2217 cmdBuffer,
2218 colorBuffer.getImage(),
2219 colorBuffer.getBuffer(),
2220 fbExtent.swizzle(0, 1),
2221 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2222 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2223 1u,
2224 VK_IMAGE_ASPECT_COLOR_BIT,
2225 VK_IMAGE_ASPECT_COLOR_BIT,
2226 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2227
2228 endCommandBuffer(ctx.vkd, cmdBuffer);
2229 submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2230
2231 // Verify color buffer has the right mip level color.
2232 const auto& colorBufferAlloc = colorBuffer.getBufferAllocation();
2233 invalidateAlloc(ctx.vkd, ctx.device, colorBufferAlloc);
2234
2235 const tcu::ConstPixelBufferAccess resultAccess (tcuFormat, fbExtent, colorBufferAlloc.getHostPtr());
2236 const auto channelThreshold = 0.005f; // 1/255 < 0.005 < 2/255
2237 const tcu::Vec4 threshold (channelThreshold, channelThreshold, channelThreshold, 0.0f);
2238
2239 if (!tcu::floatThresholdCompare(log, "Result", "", levelColors.at(static_cast<size_t>(accessedLevel)), resultAccess, threshold, tcu::COMPARE_LOG_EVERYTHING))
2240 return tcu::TestStatus::fail("Unexpected color found in color buffer -- check log for details");
2241
2242 return tcu::TestStatus::pass("Pass");
2243 }
2244
2245 } // anonymous
2246
createAllFormatsSamplerTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool separateStencilUsage=false)2247 tcu::TestCaseGroup* createAllFormatsSamplerTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool separateStencilUsage = false)
2248 {
2249 const struct
2250 {
2251 SamplerViewType type;
2252 const char* name;
2253 }
2254 imageViewTypes[] =
2255 {
2256 { VK_IMAGE_VIEW_TYPE_1D, "1d" },
2257 { { VK_IMAGE_VIEW_TYPE_1D, false }, "1d_unnormalized" },
2258 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
2259 { VK_IMAGE_VIEW_TYPE_2D, "2d" },
2260 { { VK_IMAGE_VIEW_TYPE_2D, false }, "2d_unnormalized" },
2261 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
2262 { VK_IMAGE_VIEW_TYPE_3D, "3d" },
2263 { VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
2264 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
2265 };
2266
2267 const VkFormat formats[] =
2268 {
2269 // Packed formats
2270 VK_FORMAT_R4G4_UNORM_PACK8,
2271 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2272 VK_FORMAT_R5G6B5_UNORM_PACK16,
2273 VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2274 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2275 VK_FORMAT_A2R10G10B10_UINT_PACK32,
2276 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2277 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2278 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2279 VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2280 VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
2281 VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
2282 #ifndef CTS_USES_VULKANSC
2283 VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
2284 #endif // CTS_USES_VULKANSC
2285
2286 // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
2287 VK_FORMAT_R8_SRGB,
2288 VK_FORMAT_R8G8B8_UINT,
2289 VK_FORMAT_B8G8R8A8_SINT,
2290 VK_FORMAT_R8G8_UNORM,
2291 VK_FORMAT_B8G8R8_SNORM,
2292 VK_FORMAT_R8G8B8A8_SNORM,
2293 VK_FORMAT_R8G8_UINT,
2294 VK_FORMAT_R8_SINT,
2295 VK_FORMAT_R8G8B8A8_SRGB,
2296 VK_FORMAT_R8G8B8A8_UNORM,
2297 VK_FORMAT_B8G8R8A8_UNORM,
2298 VK_FORMAT_B8G8R8_SRGB,
2299 VK_FORMAT_R8G8_SRGB,
2300 VK_FORMAT_R8_UINT,
2301 VK_FORMAT_R8G8B8A8_UINT,
2302 VK_FORMAT_R8G8_SINT,
2303 VK_FORMAT_R8_SNORM,
2304 VK_FORMAT_B8G8R8_SINT,
2305 VK_FORMAT_R8G8_SNORM,
2306 VK_FORMAT_B8G8R8_UNORM,
2307 VK_FORMAT_R8_UNORM,
2308 #ifndef CTS_USES_VULKANSC
2309 VK_FORMAT_A8_UNORM_KHR,
2310 #endif // CTS_USES_VULKANSC
2311
2312 // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
2313 VK_FORMAT_R32G32_SFLOAT,
2314 VK_FORMAT_R32G32B32_UINT,
2315 VK_FORMAT_R16G16B16A16_SFLOAT,
2316 VK_FORMAT_R16G16_UINT,
2317 VK_FORMAT_R32G32B32A32_SINT,
2318 VK_FORMAT_R16G16B16_SINT,
2319 VK_FORMAT_R16_SFLOAT,
2320 VK_FORMAT_R32_SINT,
2321 VK_FORMAT_R32_UINT,
2322 VK_FORMAT_R16G16B16_SFLOAT,
2323 VK_FORMAT_R16G16_SINT,
2324
2325 // More 16/32-bit formats required for testing VK_EXT_sampler_filter_minmax
2326 VK_FORMAT_R16_SNORM,
2327 VK_FORMAT_R32_SFLOAT,
2328
2329 // Scaled formats
2330 VK_FORMAT_R8G8B8A8_SSCALED,
2331 VK_FORMAT_A2R10G10B10_USCALED_PACK32,
2332
2333 // Compressed formats
2334 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
2335 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
2336 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
2337 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
2338 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
2339 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
2340 VK_FORMAT_EAC_R11_UNORM_BLOCK,
2341 VK_FORMAT_EAC_R11_SNORM_BLOCK,
2342 VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
2343 VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
2344 VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
2345 VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
2346 VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
2347 VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
2348 VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
2349 VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
2350 VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
2351 VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
2352 VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
2353 VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
2354
2355 // Depth formats required for testing VK_EXT_sampler_filter_minmax
2356 VK_FORMAT_D16_UNORM,
2357 VK_FORMAT_X8_D24_UNORM_PACK32,
2358 VK_FORMAT_D32_SFLOAT,
2359 VK_FORMAT_D16_UNORM_S8_UINT,
2360 VK_FORMAT_D24_UNORM_S8_UINT,
2361 VK_FORMAT_D32_SFLOAT_S8_UINT,
2362 };
2363
2364 de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type"));
2365
2366 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
2367 {
2368 const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
2369 de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
2370 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format"));
2371
2372 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2373 {
2374 const VkFormat format = formats[formatNdx];
2375 const bool isCompressed = isCompressedFormat(format);
2376 const bool isDepthStencil = !isCompressed
2377 && tcu::hasDepthComponent(mapVkFormat(format).order) && tcu::hasStencilComponent(mapVkFormat(format).order);
2378 if (isCompressed)
2379 {
2380 // Do not use compressed formats with 1D and 1D array textures.
2381 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2382 break;
2383 }
2384
2385 if (separateStencilUsage && !isDepthStencil)
2386 continue;
2387
2388 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
2389 getFormatCaseName(format).c_str(),
2390 (std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
2391
2392 if (!isCompressed && viewType.isNormalized())
2393 {
2394 // Do not include minFilter tests with compressed formats.
2395 // Randomly generated compressed textures are too noisy and will derive in false positives.
2396 de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2397 de::MovePtr<tcu::TestCaseGroup> minReduceFilterTests = createSamplerMinReduceFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2398 formatGroup->addChild(minFilterTests.release());
2399 formatGroup->addChild(minReduceFilterTests.release());
2400 }
2401
2402 de::MovePtr<tcu::TestCaseGroup> magFilterTests = createSamplerMagFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2403 formatGroup->addChild(magFilterTests.release());
2404
2405 if (viewType.isNormalized())
2406 {
2407 de::MovePtr<tcu::TestCaseGroup> magReduceFilterTests = createSamplerMagReduceFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2408 de::MovePtr<tcu::TestCaseGroup> mipmapTests = createSamplerMipmapTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2409
2410 formatGroup->addChild(magReduceFilterTests.release());
2411 formatGroup->addChild(mipmapTests.release());
2412 }
2413
2414 if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
2415 {
2416 de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2417 formatGroup->addChild(addressModesTests.release());
2418 }
2419
2420 formatTests->addChild(formatGroup.release());
2421 }
2422
2423 viewTypeGroup->addChild(formatTests.release());
2424 viewTypeTests->addChild(viewTypeGroup.release());
2425 }
2426
2427 return viewTypeTests.release();
2428 }
2429
createExactSamplingTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2430 tcu::TestCaseGroup* createExactSamplingTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2431 {
2432 de::MovePtr<tcu::TestCaseGroup> exactSamplingTests(new tcu::TestCaseGroup(testCtx, "exact_sampling"));
2433
2434 static const std::vector<vk::VkFormat> formats =
2435 {
2436 vk::VK_FORMAT_R8_SRGB,
2437 vk::VK_FORMAT_R8G8B8_UINT,
2438 vk::VK_FORMAT_B8G8R8A8_SINT,
2439 vk::VK_FORMAT_R8G8_UNORM,
2440 vk::VK_FORMAT_B8G8R8_SNORM,
2441 vk::VK_FORMAT_R8G8B8A8_SNORM,
2442 vk::VK_FORMAT_R8G8_UINT,
2443 vk::VK_FORMAT_R8_SINT,
2444 vk::VK_FORMAT_R8G8B8A8_SRGB,
2445 vk::VK_FORMAT_R8G8B8A8_UNORM,
2446 vk::VK_FORMAT_B8G8R8A8_UNORM,
2447 vk::VK_FORMAT_B8G8R8_SRGB,
2448 vk::VK_FORMAT_R8G8_SRGB,
2449 vk::VK_FORMAT_R8_UINT,
2450 vk::VK_FORMAT_R8G8B8A8_UINT,
2451 vk::VK_FORMAT_R8G8_SINT,
2452 vk::VK_FORMAT_R8_SNORM,
2453 vk::VK_FORMAT_B8G8R8_SINT,
2454 vk::VK_FORMAT_R8G8_SNORM,
2455 vk::VK_FORMAT_B8G8R8_UNORM,
2456 vk::VK_FORMAT_R8_UNORM,
2457 #ifndef CTS_USES_VULKANSC
2458 vk::VK_FORMAT_A8_UNORM_KHR,
2459 #endif // CTS_USES_VULKANSC
2460
2461 vk::VK_FORMAT_R32G32_SFLOAT,
2462 vk::VK_FORMAT_R32G32B32_UINT,
2463 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
2464 vk::VK_FORMAT_R16G16_UINT,
2465 vk::VK_FORMAT_R32G32B32A32_SINT,
2466 vk::VK_FORMAT_R16G16B16_SINT,
2467 vk::VK_FORMAT_R16_SFLOAT,
2468 vk::VK_FORMAT_R32_SINT,
2469 vk::VK_FORMAT_R32_UINT,
2470 vk::VK_FORMAT_R16G16B16_SFLOAT,
2471 vk::VK_FORMAT_R16G16_SINT,
2472
2473 vk::VK_FORMAT_R16_SNORM,
2474 vk::VK_FORMAT_R32_SFLOAT,
2475 };
2476
2477 static const struct
2478 {
2479 const bool unnormalized;
2480 const std::string name;
2481 } unnormalizedCoordinates[] =
2482 {
2483 // Normalized coordinates
2484 { false, "normalized_coords"},
2485 // Unnormalized coordinates
2486 { true, "unnormalized_coords"},
2487 };
2488
2489 static const struct
2490 {
2491 const tcu::Maybe<float> offset;
2492 const std::string name;
2493 } testEdges[] =
2494 {
2495 // Sampling points centered in texel
2496 { tcu::Nothing, "centered"},
2497 // Sampling points near left edge
2498 { tcu::just<float>(-1.0f), "edge_left"},
2499 // Sampling points near right edge
2500 { tcu::just<float>(+1.0f), "edge_right"},
2501 };
2502
2503 static const std::vector<std::pair<bool, std::string>> solidColor =
2504 {
2505 { false, "gradient" },
2506 { true, "solid_color" },
2507 };
2508
2509 for (const auto format : formats)
2510 {
2511 const std::string formatName = getFormatCaseName(format);
2512
2513 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
2514
2515 for (const auto& solid : solidColor)
2516 {
2517 de::MovePtr<tcu::TestCaseGroup> solidColorGroup(new tcu::TestCaseGroup(testCtx, solid.second.c_str()));
2518
2519 for (int unIdx = 0; unIdx < DE_LENGTH_OF_ARRAY(unnormalizedCoordinates); ++unIdx)
2520 {
2521 const auto& unnorm = unnormalizedCoordinates[unIdx];
2522 de::MovePtr<tcu::TestCaseGroup> coordGroup (new tcu::TestCaseGroup(testCtx, unnorm.name.c_str()));
2523
2524 for (int edgeIdx = 0; edgeIdx < DE_LENGTH_OF_ARRAY(testEdges); ++edgeIdx)
2525 {
2526 const auto& edges = testEdges[edgeIdx];
2527 const ExactSamplingCase::Params params = { pipelineConstructionType, format, unnorm.unnormalized, solid.first, edges.offset };
2528 coordGroup->addChild(new ExactSamplingCase{testCtx, edges.name, params});
2529 }
2530
2531 solidColorGroup->addChild(coordGroup.release());
2532 }
2533
2534 formatGroup->addChild(solidColorGroup.release());
2535 }
2536
2537 exactSamplingTests->addChild(formatGroup.release());
2538 }
2539
2540 return exactSamplingTests.release();
2541 }
2542
createMaxSamplerLodBiasTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2543 tcu::TestCaseGroup* createMaxSamplerLodBiasTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2544 {
2545 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "max_sampler_lod_bias", "Test the maxSamplerLodBias limit"));
2546
2547 for (int caseIdx = 0; caseIdx < static_cast<int>(LodBiasCase::CASE_COUNT); ++caseIdx)
2548 {
2549 const auto caseValue = static_cast<LodBiasCase>(caseIdx);
2550 const auto testName = getLodBiasCaseName(caseValue);
2551 const MaxSamplerLodBiasParams params {pipelineConstructionType, caseValue};
2552
2553 #ifdef CTS_USES_VULKANSC
2554 if (caseValue == LodBiasCase::VIEW_MINLOD)
2555 continue;
2556 #endif // CTS_USES_VULKANSC
2557
2558 testGroup->addChild(new MaxSamplerLodBiasCase(testCtx, testName, params));
2559 }
2560
2561 return testGroup.release();
2562 }
2563
createSamplerTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2564 tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2565 {
2566 de::MovePtr<tcu::TestCaseGroup> samplerTests(new tcu::TestCaseGroup(testCtx, "sampler"));
2567 {
2568 samplerTests->addChild(createAllFormatsSamplerTests(testCtx, pipelineConstructionType));
2569 samplerTests->addChild(createExactSamplingTests(testCtx, pipelineConstructionType));
2570 }
2571
2572 // tests for VK_EXT_separate_stencil_usage
2573 de::MovePtr<tcu::TestCaseGroup> separateStencilUsageSamplerTests (new tcu::TestCaseGroup(testCtx, "separate_stencil_usage"));
2574 {
2575 separateStencilUsageSamplerTests->addChild(createAllFormatsSamplerTests(testCtx, pipelineConstructionType, true));
2576 samplerTests->addChild(separateStencilUsageSamplerTests.release());
2577 }
2578
2579 #ifndef CTS_USES_VULKANSC
2580 // Border color swizzle tests.
2581 samplerTests->addChild(createSamplerBorderSwizzleTests(testCtx, pipelineConstructionType));
2582 #endif // CTS_USES_VULKANSC
2583
2584 samplerTests->addChild(createMaxSamplerLodBiasTests(testCtx, pipelineConstructionType));
2585
2586 return samplerTests.release();
2587 }
2588
2589 } // pipeline
2590 } // vkt
2591