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