• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google Inc.
7  * Copyright (c) 2022 LunarG, Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Tests dithering
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRenderPassLoadStoreOpNoneTests.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 #include "vktRenderPassTestsUtil.hpp"
29 #include "pipeline/vktPipelineImageUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "vktTestGroupUtil.hpp"
37 
38 namespace vkt
39 {
40 namespace renderpass
41 {
42 
43 using namespace vk;
44 
45 namespace
46 {
47 
48 // ~1 ULP in D24_UNORM (1/2^24 == 0.00000006)
49 const uint32_t baseDepthValue       = 0b00111110000000000000000000000000; // 0.125f
50 const uint32_t oneUlpMoreDepthValue = 0b00111110000000000000000000000101; // 0.125000074506f
51 const uint32_t oneUlpLessDepthValue = 0b00111101111111111111111111110111; // 0.124999932945f
52 
53 struct TestParams
54 {
55     std::vector<VkViewport> renderAreas;
56     std::vector<VkFormat> colorFormats;
57     tcu::Vec4 overrideColor;
58     tcu::UVec2 imageSize;
59     VkFormat depthStencilFormat;
60     SharedGroupParams groupParams;
61     VkBlendFactor srcFactor;
62     VkBlendFactor dstFactor;
63     uint32_t stencilClearValue;
64     VkCompareOp depthCompareOp;
65     float depthClearValue;
66     bool blending;
67     bool revision2;
68 };
69 
70 struct Vertex4RGBA
71 {
72     tcu::Vec4 position;
73     tcu::Vec4 color;
74 };
75 
76 de::SharedPtr<Move<vk::VkDevice>> g_singletonDevice;
77 
getDevice(Context & context)78 VkDevice getDevice(Context &context)
79 {
80     if (g_singletonDevice)
81         return g_singletonDevice->get();
82 
83     // Create a universal queue that supports graphics and compute
84     const float queuePriority = 1.0f;
85     const VkDeviceQueueCreateInfo queueParams{
86         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
87         nullptr,                                    // const void* pNext;
88         0u,                                         // VkDeviceQueueCreateFlags flags;
89         context.getUniversalQueueFamilyIndex(),     // uint32_t queueFamilyIndex;
90         1u,                                         // uint32_t queueCount;
91         &queuePriority                              // const float* pQueuePriorities;
92     };
93 
94     // \note Extensions in core are not explicitly enabled even though
95     //         they are in the extension list advertised to tests.
96     const auto &extensionPtrs = context.getDeviceCreationExtensions();
97 
98     VkPhysicalDeviceLegacyDitheringFeaturesEXT legacyDitheringFeatures = initVulkanStructure();
99     VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures  = initVulkanStructure();
100     VkPhysicalDeviceFeatures2 features2                                = initVulkanStructure();
101 
102     const auto addFeatures = makeStructChainAdder(&features2);
103     addFeatures(&legacyDitheringFeatures);
104 
105     if (context.isDeviceFunctionalitySupported("VK_KHR_dynamic_rendering"))
106         addFeatures(&dynamicRenderingFeatures);
107 
108     context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
109     features2.features.robustBufferAccess = VK_FALSE;
110 
111     const VkDeviceCreateInfo deviceCreateInfo{
112         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
113         &features2,                           //pNext;
114         0u,                                   //flags
115         1,                                    //queueRecordCount;
116         &queueParams,                         //pRequestedQueues;
117         0u,                                   //layerCount;
118         nullptr,                              //ppEnabledLayerNames;
119         de::sizeU32(extensionPtrs),           // uint32_t enabledExtensionCount;
120         de::dataOrNull(extensionPtrs),        // const char* const* ppEnabledExtensionNames;
121         nullptr,                              //pEnabledFeatures;
122     };
123 
124     Move<VkDevice> device = createCustomDevice(
125         context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(),
126         context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceCreateInfo);
127     g_singletonDevice = de::SharedPtr<Move<VkDevice>>(new Move<VkDevice>(device));
128     return g_singletonDevice->get();
129 }
130 
createQuad(void)131 std::vector<Vertex4RGBA> createQuad(void)
132 {
133     std::vector<Vertex4RGBA> vertices;
134 
135     const float size = 1.0f;
136     const tcu::Vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
137     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
138     const tcu::Vec4 blue(0.0f, 0.0f, 1.0f, 1.0f);
139     const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f);
140     const float *ptr                   = reinterpret_cast<const float *>(&baseDepthValue);
141     const float depthValue             = *(ptr);
142     const Vertex4RGBA lowerLeftVertex  = {tcu::Vec4(-size, -size, depthValue, 1.0f), red};
143     const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, depthValue, 1.0f), green};
144     const Vertex4RGBA upperLeftVertex  = {tcu::Vec4(-size, size, depthValue, 1.0f), blue};
145     const Vertex4RGBA upperRightVertex = {tcu::Vec4(size, size, depthValue, 1.0f), white};
146 
147     vertices.push_back(lowerLeftVertex);
148     vertices.push_back(upperLeftVertex);
149     vertices.push_back(lowerRightVertex);
150     vertices.push_back(upperLeftVertex);
151     vertices.push_back(upperRightVertex);
152     vertices.push_back(lowerRightVertex);
153 
154     return vertices;
155 }
156 
createQuad(const tcu::Vec4 & color)157 std::vector<Vertex4RGBA> createQuad(const tcu::Vec4 &color)
158 {
159     std::vector<Vertex4RGBA> vertices;
160 
161     const float size                   = 1.0f;
162     const float *ptr                   = reinterpret_cast<const float *>(&baseDepthValue);
163     const float depthValue             = *(ptr);
164     const Vertex4RGBA lowerLeftVertex  = {tcu::Vec4(-size, -size, depthValue, 1.0f), color};
165     const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, depthValue, 1.0f), color};
166     const Vertex4RGBA upperLeftVertex  = {tcu::Vec4(-size, size, depthValue, 1.0f), color};
167     const Vertex4RGBA upperRightVertex = {tcu::Vec4(size, size, depthValue, 1.0f), color};
168 
169     vertices.push_back(lowerLeftVertex);
170     vertices.push_back(upperLeftVertex);
171     vertices.push_back(lowerRightVertex);
172     vertices.push_back(upperLeftVertex);
173     vertices.push_back(upperRightVertex);
174     vertices.push_back(lowerRightVertex);
175 
176     return vertices;
177 }
178 
179 class DitheringTest : public vkt::TestCase
180 {
181 public:
182     DitheringTest(tcu::TestContext &testContext, const std::string &name, TestParams testParams);
183     virtual ~DitheringTest(void);
184     virtual void initPrograms(SourceCollections &sourceCollections) const;
185     virtual void checkSupport(Context &context) const;
186     virtual TestInstance *createInstance(Context &context) const;
187 
188 private:
189     TestParams m_testParams;
190 };
191 
192 class DitheringTestInstance : public vkt::TestInstance
193 {
194 public:
195     DitheringTestInstance(Context &context, TestParams testParams);
196     virtual ~DitheringTestInstance(void);
197     virtual tcu::TestStatus iterate(void);
198 
199 private:
200     template <typename RenderpassSubpass>
201     void render(const VkViewport &vp, bool useDithering);
202     void createCommonResources(void);
203     void createDrawResources(bool useDithering);
204 
205     template <typename AttachmentDescription, typename AttachmentReference, typename SubpassDescription,
206               typename RenderPassCreateInfo>
207     void createRenderPassFramebuffer(bool useDithering);
208 
209     // Data.
210 private:
211     TestParams m_testParams;
212 
213     // Common resources.
214     SimpleAllocator m_memAlloc;
215     Move<VkBuffer> m_vertexBuffer;
216     de::MovePtr<Allocation> m_vertexBufferAlloc;
217     Move<VkPipelineLayout> m_pipelineLayout;
218     Move<VkShaderModule> m_vertexShaderModule;
219     Move<VkShaderModule> m_fragmentShaderModule;
220 
221     struct DrawResources
222     {
223         std::vector<Move<VkImage>> attachmentImages;
224         std::vector<de::MovePtr<Allocation>> attachmentImageAllocs;
225         std::vector<Move<VkImageView>> imageViews;
226         Move<VkImage> depthStencilImage;
227         de::MovePtr<Allocation> depthStencilImageAlloc;
228         Move<VkImageView> depthStencilImageView;
229         Move<VkRenderPass> renderPass;
230         Move<VkFramebuffer> framebuffer;
231         Move<VkPipeline> pipeline;
232     };
233     const uint32_t m_noDitheringNdx = 0u;
234     const uint32_t m_ditheringNdx   = 1u;
235 
236     // 0 for no dithering and 1 for dithering resources.
237     DrawResources m_drawResources[2];
238 };
239 
DitheringTest(tcu::TestContext & testContext,const std::string & name,TestParams testParams)240 DitheringTest::DitheringTest(tcu::TestContext &testContext, const std::string &name, TestParams testParams)
241     : vkt::TestCase(testContext, name)
242     , m_testParams(testParams)
243 {
244 }
245 
~DitheringTest(void)246 DitheringTest::~DitheringTest(void)
247 {
248 }
249 
initPrograms(SourceCollections & sourceCollections) const250 void DitheringTest::initPrograms(SourceCollections &sourceCollections) const
251 {
252     sourceCollections.glslSources.add("color_vert")
253         << glu::VertexSource("#version 450\n"
254                              "layout(location = 0) in highp vec4 position;\n"
255                              "layout(location = 1) in highp vec4 color;\n"
256                              "layout(location = 0) out highp vec4 vtxColor;\n"
257                              "void main (void)\n"
258                              "{\n"
259                              "    gl_Position = position;\n"
260                              "    vtxColor = color;\n"
261                              "}\n");
262 
263     sourceCollections.glslSources.add("color_frag")
264         << glu::FragmentSource("#version 450\n"
265                                "layout(location = 0) in highp vec4 vtxColor;\n"
266                                "layout(location = 0) out highp vec4 fragColor0;\n"
267                                "layout(location = 1) out highp vec4 fragColor1;\n"
268                                "layout(location = 2) out highp vec4 fragColor2;\n"
269                                "void main (void)\n"
270                                "{\n"
271                                "    fragColor0 = vtxColor;\n"
272                                "    fragColor1 = vtxColor;\n"
273                                "    fragColor2 = vtxColor;\n"
274                                "}\n");
275 }
276 
checkSupport(Context & ctx) const277 void DitheringTest::checkSupport(Context &ctx) const
278 {
279     // Check for renderpass2 extension if used.
280     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
281         ctx.requireDeviceFunctionality("VK_KHR_create_renderpass2");
282 
283     // Check for dynamic_rendering extension if used
284     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
285         ctx.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
286 
287     ctx.requireDeviceFunctionality("VK_EXT_legacy_dithering");
288 
289     uint32_t specVersion = 0;
290     const auto extensionProperties =
291         vk::enumerateDeviceExtensionProperties(ctx.getInstanceInterface(), ctx.getPhysicalDevice(), nullptr);
292     for (const auto &extProp : extensionProperties)
293     {
294         if (strcmp(extProp.extensionName, "VK_EXT_legacy_dithering") == 0)
295         {
296             specVersion = extProp.specVersion;
297             break;
298         }
299     }
300 
301     if (m_testParams.revision2)
302     {
303         ctx.requireDeviceFunctionality("VK_KHR_maintenance5");
304 
305         if (specVersion < 2)
306             TCU_THROW(NotSupportedError, "VK_EXT_legacy_dithering specVersion at least 2 is required");
307     }
308     else
309     {
310         if (specVersion > 1)
311             TCU_THROW(NotSupportedError, "VK_EXT_legacy_dithering specVersion at 1 is required");
312     }
313 
314     // Check color format support.
315     for (const VkFormat format : m_testParams.colorFormats)
316     {
317         VkImageUsageFlags usage =
318             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
319         const auto &vki    = ctx.getInstanceInterface();
320         const auto physDev = ctx.getPhysicalDevice();
321         const auto imgType = VK_IMAGE_TYPE_2D;
322         const auto tiling  = VK_IMAGE_TILING_OPTIMAL;
323         VkImageFormatProperties properties;
324 
325         const auto result =
326             vki.getPhysicalDeviceImageFormatProperties(physDev, format, imgType, tiling, usage, 0u, &properties);
327 
328         if (result != VK_SUCCESS)
329             TCU_THROW(NotSupportedError, "Color format not supported");
330     }
331 
332     // Check depth stencil format support.
333     if (m_testParams.depthStencilFormat != VK_FORMAT_UNDEFINED)
334     {
335         VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
336                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
337         const auto &vki    = ctx.getInstanceInterface();
338         const auto physDev = ctx.getPhysicalDevice();
339         const auto imgType = VK_IMAGE_TYPE_2D;
340         const auto tiling  = VK_IMAGE_TILING_OPTIMAL;
341         VkImageFormatProperties properties;
342 
343         const auto result = vki.getPhysicalDeviceImageFormatProperties(physDev, m_testParams.depthStencilFormat,
344                                                                        imgType, tiling, usage, 0u, &properties);
345 
346         if (result != VK_SUCCESS)
347             TCU_THROW(NotSupportedError, "Depth/stencil format not supported");
348     }
349 }
350 
createInstance(Context & context) const351 TestInstance *DitheringTest::createInstance(Context &context) const
352 {
353     return new DitheringTestInstance(context, m_testParams);
354 }
355 
DitheringTestInstance(Context & context,TestParams testParams)356 DitheringTestInstance::DitheringTestInstance(Context &context, TestParams testParams)
357     : vkt::TestInstance(context)
358     , m_testParams(testParams)
359     , m_memAlloc(context.getDeviceInterface(), getDevice(context),
360                  getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
361 {
362     createCommonResources();
363     createDrawResources(false); // No dithering
364     createDrawResources(true);  // Dithering
365 }
366 
~DitheringTestInstance(void)367 DitheringTestInstance::~DitheringTestInstance(void)
368 {
369 }
370 
iterate(void)371 tcu::TestStatus DitheringTestInstance::iterate(void)
372 {
373     const DeviceInterface &vk       = m_context.getDeviceInterface();
374     const VkDevice vkDevice         = getDevice(m_context);
375     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
376     const VkQueue queue             = getDeviceQueue(vk, vkDevice, queueFamilyIndex, 0);
377 
378     for (const VkViewport &vp : m_testParams.renderAreas)
379     {
380         if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
381         {
382             render<RenderpassSubpass1>(vp, false);
383             render<RenderpassSubpass1>(vp, true);
384         }
385         else
386         {
387             render<RenderpassSubpass2>(vp, false);
388             render<RenderpassSubpass2>(vp, true);
389         }
390 
391         // Check output matches to expected within one ULP.
392         for (uint32_t i = 0u; i < m_testParams.colorFormats.size(); ++i)
393         {
394             VkFormat format      = m_testParams.colorFormats[i];
395             VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
396 
397             // No dithering
398             SimpleAllocator imageAllocator(
399                 vk, vkDevice,
400                 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
401             de::MovePtr<tcu::TextureLevel> referenceTextureLevelResult = pipeline::readColorAttachment(
402                 vk, vkDevice, queue, queueFamilyIndex, imageAllocator,
403                 *m_drawResources[m_noDitheringNdx].attachmentImages[i], format, m_testParams.imageSize, layout);
404             const tcu::ConstPixelBufferAccess &referenceAccess = referenceTextureLevelResult->getAccess();
405 
406             // Dithering
407             de::MovePtr<tcu::TextureLevel> resultTextureLevelResult = pipeline::readColorAttachment(
408                 vk, vkDevice, queue, queueFamilyIndex, imageAllocator,
409                 *m_drawResources[m_ditheringNdx].attachmentImages[i], format, m_testParams.imageSize, layout);
410             const tcu::ConstPixelBufferAccess &resultAccess = resultTextureLevelResult->getAccess();
411 
412             // 1 ULP will always be 1 bit difference no matter the format
413             // However, we allow N ULP for additive blending tests since drivers may do dithering while rendering (per draw)
414             // which can cause dither pattern to exceed 1ULP threshold with additive blending, see discussion in:
415             // https://gitlab.khronos.org/Tracker/vk-gl-cts/-/issues/3785#note_384389
416             const uint32_t n_ulp = (m_testParams.blending && m_testParams.dstFactor == VK_BLEND_FACTOR_ONE) ? 4u : 1u;
417             const tcu::UVec4 threshold(n_ulp, n_ulp, n_ulp, n_ulp);
418 
419             if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "", "", referenceAccess, resultAccess,
420                                           threshold, tcu::COMPARE_LOG_ON_ERROR))
421                 return tcu::TestStatus::fail("Fail");
422         }
423 
424         // Check depth/stencil
425         if (m_testParams.depthStencilFormat != VK_FORMAT_UNDEFINED)
426         {
427             VkFormat format      = m_testParams.depthStencilFormat;
428             VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
429 
430             // Depth check.
431             {
432                 // No dithering
433                 SimpleAllocator imageAllocator(
434                     vk, vkDevice,
435                     getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
436                 de::MovePtr<tcu::TextureLevel> referenceTextureLevelResult = pipeline::readDepthAttachment(
437                     vk, vkDevice, queue, queueFamilyIndex, imageAllocator,
438                     *m_drawResources[m_noDitheringNdx].depthStencilImage, format, m_testParams.imageSize, layout);
439                 const tcu::ConstPixelBufferAccess &referenceAccess = referenceTextureLevelResult->getAccess();
440 
441                 // Dithering
442                 de::MovePtr<tcu::TextureLevel> resultTextureLevelResult = pipeline::readDepthAttachment(
443                     vk, vkDevice, queue, queueFamilyIndex, imageAllocator,
444                     *m_drawResources[m_ditheringNdx].depthStencilImage, format, m_testParams.imageSize, layout);
445                 const tcu::ConstPixelBufferAccess &resultAccess = resultTextureLevelResult->getAccess();
446 
447                 // Depth should be unaffected by dithering
448                 const float threshold = 0.0f;
449 
450                 if (!tcu::dsThresholdCompare(m_context.getTestContext().getLog(), "", "", referenceAccess, resultAccess,
451                                              threshold, tcu::COMPARE_LOG_ON_ERROR))
452                     return tcu::TestStatus::fail("Fail");
453             }
454 
455             // Stencil check.
456             {
457                 // No dithering
458                 SimpleAllocator imageAllocator(
459                     vk, vkDevice,
460                     getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
461                 de::MovePtr<tcu::TextureLevel> referenceTextureLevelResult = pipeline::readStencilAttachment(
462                     vk, vkDevice, queue, queueFamilyIndex, imageAllocator,
463                     *m_drawResources[m_noDitheringNdx].depthStencilImage, format, m_testParams.imageSize, layout);
464                 const tcu::ConstPixelBufferAccess &referenceAccess = referenceTextureLevelResult->getAccess();
465 
466                 // Dithering
467                 de::MovePtr<tcu::TextureLevel> resultTextureLevelResult = pipeline::readStencilAttachment(
468                     vk, vkDevice, queue, queueFamilyIndex, imageAllocator,
469                     *m_drawResources[m_ditheringNdx].depthStencilImage, format, m_testParams.imageSize, layout);
470                 const tcu::ConstPixelBufferAccess &resultAccess = resultTextureLevelResult->getAccess();
471 
472                 // Stencil should be unaffected by dithering
473                 const float threshold = 0.0f;
474 
475                 if (!tcu::dsThresholdCompare(m_context.getTestContext().getLog(), "", "", referenceAccess, resultAccess,
476                                              threshold, tcu::COMPARE_LOG_ON_ERROR))
477                     return tcu::TestStatus::fail("Fail");
478             }
479         }
480     }
481 
482     return tcu::TestStatus::pass("Pass");
483 }
484 
485 template <typename RenderpassSubpass>
render(const VkViewport & vp,bool useDithering)486 void DitheringTestInstance::render(const VkViewport &vp, bool useDithering)
487 {
488     const DeviceInterface &vk       = m_context.getDeviceInterface();
489     const VkDevice vkDevice         = getDevice(m_context);
490     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
491     const VkQueue queue             = getDeviceQueue(vk, vkDevice, queueFamilyIndex, 0);
492 
493     uint32_t resourceNdx       = useDithering ? m_ditheringNdx : m_noDitheringNdx;
494     const tcu::UVec2 imageSize = m_testParams.imageSize;
495     const bool useDepthStencil = (m_testParams.depthStencilFormat != VK_FORMAT_UNDEFINED);
496 
497     // Clear color and transition image to desired layout.
498     {
499         const auto dstAccess = (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
500                                 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
501         const auto dstStage  = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
502         const auto layout    = (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) ?
503                                    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL :
504                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
505         auto clearColor      = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
506 
507         if (m_testParams.blending)
508             clearColor = makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f).color;
509 
510         for (const auto &image : m_drawResources[resourceNdx].attachmentImages)
511             clearColorImage(vk, vkDevice, queue, queueFamilyIndex, *image, clearColor,
512                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout, dstAccess, dstStage);
513     }
514 
515     // Clear depth/stencil.
516     if (useDepthStencil)
517     {
518         const auto dstAccess =
519             (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
520         const auto dstStage = (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
521         const auto layout   = m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING ?
522                                   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL :
523                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
524 
525         clearDepthStencilImage(vk, vkDevice, queue, queueFamilyIndex, *m_drawResources[resourceNdx].depthStencilImage,
526                                m_testParams.depthStencilFormat, m_testParams.depthClearValue,
527                                m_testParams.stencilClearValue, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout, dstAccess,
528                                dstStage);
529     }
530 
531     // Rendering.
532     {
533         // Create command pool and allocate command buffer.
534         Move<VkCommandPool> cmdPool =
535             createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
536         Move<VkCommandBuffer> cmdBuffer =
537             allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
538 
539         const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(nullptr, VK_SUBPASS_CONTENTS_INLINE);
540         const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(nullptr);
541         const VkDeviceSize vertexBufferOffset = 0;
542         const uint32_t drawCount = (m_testParams.blending && m_testParams.dstFactor == VK_BLEND_FACTOR_ONE) ? 4u : 1u;
543 
544         beginCommandBuffer(vk, *cmdBuffer, 0u);
545 
546         if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
547         {
548             std::vector<VkRenderingAttachmentInfoKHR> colorAttachments;
549 
550             for (const auto &imageView : m_drawResources[resourceNdx].imageViews)
551             {
552                 VkRenderingAttachmentInfoKHR attachment = {
553                     VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,       // VkStructureType sType;
554                     nullptr,                                               // const void* pNext;
555                     *imageView,                                            // VkImageView imageView;
556                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,              // VkImageLayout imageLayout;
557                     VK_RESOLVE_MODE_NONE,                                  // VkResolveModeFlagBits resolveMode;
558                     VK_NULL_HANDLE,                                        // VkImageView resolveImageView;
559                     VK_IMAGE_LAYOUT_UNDEFINED,                             // VkImageLayout resolveImageLayout;
560                     VK_ATTACHMENT_LOAD_OP_LOAD,                            // VkAttachmentLoadOp loadOp;
561                     VK_ATTACHMENT_STORE_OP_STORE,                          // VkAttachmentStoreOp storeOp;
562                     makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) // VkClearValue clearValue;
563                 };
564 
565                 colorAttachments.emplace_back(attachment);
566             }
567 
568             VkRenderingAttachmentInfoKHR dsAttachment = {
569                 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,     // VkStructureType sType;
570                 nullptr,                                             // const void* pNext;
571                 *m_drawResources[resourceNdx].depthStencilImageView, // VkImageView imageView;
572                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,    // VkImageLayout imageLayout;
573                 VK_RESOLVE_MODE_NONE,                                // VkResolveModeFlagBits resolveMode;
574                 VK_NULL_HANDLE,                                      // VkImageView resolveImageView;
575                 VK_IMAGE_LAYOUT_UNDEFINED,                           // VkImageLayout resolveImageLayout;
576                 VK_ATTACHMENT_LOAD_OP_LOAD,                          // VkAttachmentLoadOp loadOp;
577                 VK_ATTACHMENT_STORE_OP_STORE,                        // VkAttachmentStoreOp storeOp;
578                 makeClearValueDepthStencil(m_testParams.depthClearValue,
579                                            m_testParams.stencilClearValue) // VkClearValue clearValue;
580             };
581 
582             VkRenderingFlags renderingInfoFlags = 0u;
583             if (useDithering)
584                 renderingInfoFlags = VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT;
585             VkRenderingInfoKHR renderingInfo = {
586                 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,      // VkStructureType sType;
587                 nullptr,                                   // const void* pNext;
588                 renderingInfoFlags,                        // VkRenderingFlagsKHR flags;
589                 makeRect2D(imageSize),                     // VkRect2D renderArea;
590                 1u,                                        // uint32_t layerCount;
591                 0u,                                        // uint32_t viewMask;
592                 (uint32_t)colorAttachments.size(),         // uint32_t colorAttachmentCount;
593                 colorAttachments.data(),                   // const VkRenderingAttachmentInfoKHR* pColorAttachments;
594                 useDepthStencil ? &dsAttachment : nullptr, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
595                 useDepthStencil ? &dsAttachment : nullptr  // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
596             };
597 
598             vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
599         }
600         else
601         {
602             const VkRenderPassBeginInfo renderPassBeginInfo = {
603                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,  // VkStructureType        sType
604                 nullptr,                                   // const void*            pNext
605                 *m_drawResources[resourceNdx].renderPass,  // VkRenderPass            renderPass
606                 *m_drawResources[resourceNdx].framebuffer, // VkFramebuffer        framebuffer
607                 makeRect2D(imageSize),                     // VkRect2D                renderArea
608                 0u,                                        // uint32_t                clearValueCount
609                 nullptr                                    // const VkClearValue*    pClearValues
610             };
611             RenderpassSubpass::cmdBeginRenderPass(vk, *cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
612         }
613 
614         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
615         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_drawResources[resourceNdx].pipeline);
616         vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &vp);
617         for (uint32_t i = 0u; i < drawCount; ++i)
618             vk.cmdDraw(*cmdBuffer, 6u, 1, 0, 0);
619 
620         if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
621             vk.cmdEndRendering(*cmdBuffer);
622         else
623             RenderpassSubpass::cmdEndRenderPass(vk, *cmdBuffer, &subpassEndInfo);
624         endCommandBuffer(vk, *cmdBuffer);
625 
626         // Submit commands.
627         submitCommandsAndWait(vk, vkDevice, queue, cmdBuffer.get());
628     }
629 }
630 
createCommonResources(void)631 void DitheringTestInstance::createCommonResources(void)
632 {
633     const DeviceInterface &vk       = m_context.getDeviceInterface();
634     const VkDevice vkDevice         = getDevice(m_context);
635     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
636 
637     // Shaders.
638     m_vertexShaderModule   = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
639     m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
640 
641     // Vertex buffer.
642     {
643         const std::vector<Vertex4RGBA> vertices =
644             m_testParams.blending ? createQuad(m_testParams.overrideColor) : createQuad();
645         const VkBufferCreateInfo vertexBufferParams = {
646             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                  // VkStructureType        sType
647             nullptr,                                               // const void*            pNext
648             0u,                                                    // VkBufferCreateFlags    flags
649             (VkDeviceSize)(sizeof(Vertex4RGBA) * vertices.size()), // VkDeviceSize            size
650             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                     // VkBufferUsageFlags    usage
651             VK_SHARING_MODE_EXCLUSIVE,                             // VkSharingMode        sharingMode
652             1u,                                                    // uint32_t                queueFamilyIndexCount
653             &queueFamilyIndex                                      // const uint32_t*        pQueueFamilyIndices
654         };
655 
656         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
657         m_vertexBufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
658                                                   MemoryRequirement::HostVisible);
659 
660         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
661                                      m_vertexBufferAlloc->getOffset()));
662 
663         // Upload vertex data.
664         deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(Vertex4RGBA));
665         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
666     }
667 
668     // Create pipeline layout.
669     {
670         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
671             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                sType
672             nullptr,                                       // const void*                    pNext
673             0u,                                            // VkPipelineLayoutCreateFlags    flags
674             0u,                                            // uint32_t                        setLayoutCount
675             nullptr,                                       // const VkDescriptorSetLayout*    pSetLayouts
676             0u,                                            // uint32_t                        pushConstantRangeCount
677             nullptr                                        // const VkPushConstantRange*    pPushConstantRanges
678         };
679 
680         m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
681     }
682 }
683 
createDrawResources(bool useDithering)684 void DitheringTestInstance::createDrawResources(bool useDithering)
685 {
686     const DeviceInterface &vk       = m_context.getDeviceInterface();
687     const VkDevice vkDevice         = getDevice(m_context);
688     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
689     const VkQueue queue             = getDeviceQueue(vk, vkDevice, queueFamilyIndex, 0);
690 
691     uint32_t resourceNdx                              = useDithering ? m_ditheringNdx : m_noDitheringNdx;
692     const std::vector<vk::VkFormat> colorFormats      = m_testParams.colorFormats;
693     const tcu::UVec2 &imageSize                       = m_testParams.imageSize;
694     const VkComponentMapping componentMappingIdentity = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
695                                                          VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
696 
697     // Attachment images and views.
698     for (const VkFormat format : colorFormats)
699     {
700         VkImageUsageFlags usage =
701             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
702         VkImageAspectFlags aspectFlags          = VK_IMAGE_ASPECT_COLOR_BIT;
703         const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
704         const VkImageCreateInfo imageParams     = {
705             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
706             nullptr,                             // const void*                pNext
707             0u,                                  // VkImageCreateFlags        flags
708             VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
709             format,                              // VkFormat                    format
710             {imageSize.x(), imageSize.y(), 1u},  // VkExtent3D                extent
711             1u,                                  // uint32_t                    mipLevels
712             1u,                                  // uint32_t                    arrayLayers
713             sampleCount,                         // VkSampleCountFlagBits    samples
714             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
715             usage,                               // VkImageUsageFlags        usage
716             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
717             1u,                                  // uint32_t                    queueFamilyIndexCount
718             &queueFamilyIndex,                   // const uint32_t*            pQueueFamilyIndices
719             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
720         };
721         Move<VkImage> image                     = createImage(vk, vkDevice, &imageParams);
722         VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vk, vkDevice, *image);
723         de::MovePtr<Allocation> imageAlloc      = m_memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
724         VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageAlloc->getMemory(), imageAlloc->getOffset()));
725 
726         // Create image view.
727         const VkImageViewCreateInfo imageViewParams = {
728             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
729             nullptr,                                  // const void*                pNext
730             0u,                                       // VkImageViewCreateFlags    flags
731             *image,                                   // VkImage                    image
732             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
733             format,                                   // VkFormat                    format
734             componentMappingIdentity,                 // VkChannelMapping            channels
735             {aspectFlags, 0u, 1u, 0u, 1u}             // VkImageSubresourceRange    subresourceRange
736         };
737         Move<VkImageView> imageView = createImageView(vk, vkDevice, &imageViewParams);
738 
739         // Clear and transition image to desired layout for easier looping later when rendering.
740         {
741             const auto dstAccess = (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
742                                     VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
743             const auto dstStage =
744                 (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
745             const auto clearColor = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
746             const auto layout     = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
747 
748             clearColorImage(vk, vkDevice, queue, queueFamilyIndex, *image, clearColor, VK_IMAGE_LAYOUT_UNDEFINED,
749                             layout, dstAccess, dstStage);
750         }
751 
752         // Store resources.
753         m_drawResources[resourceNdx].attachmentImages.emplace_back(image);
754         m_drawResources[resourceNdx].attachmentImageAllocs.emplace_back(imageAlloc);
755         m_drawResources[resourceNdx].imageViews.emplace_back(imageView);
756     }
757 
758     // Depth stencil image and view.
759     if (m_testParams.depthStencilFormat != VK_FORMAT_UNDEFINED)
760     {
761         VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
762                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
763         VkImageAspectFlags aspectFlags          = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
764         const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
765         const VkImageCreateInfo imageParams     = {
766             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
767             nullptr,                             // const void*                pNext
768             0u,                                  // VkImageCreateFlags        flags
769             VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
770             m_testParams.depthStencilFormat,     // VkFormat                    format
771             {imageSize.x(), imageSize.y(), 1u},  // VkExtent3D                extent
772             1u,                                  // uint32_t                    mipLevels
773             1u,                                  // uint32_t                    arrayLayers
774             sampleCount,                         // VkSampleCountFlagBits    samples
775             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
776             usage,                               // VkImageUsageFlags        usage
777             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
778             1u,                                  // uint32_t                    queueFamilyIndexCount
779             &queueFamilyIndex,                   // const uint32_t*            pQueueFamilyIndices
780             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
781         };
782         m_drawResources[resourceNdx].depthStencilImage      = createImage(vk, vkDevice, &imageParams);
783         m_drawResources[resourceNdx].depthStencilImageAlloc = m_memAlloc.allocate(
784             getImageMemoryRequirements(vk, vkDevice, *m_drawResources[resourceNdx].depthStencilImage),
785             MemoryRequirement::Any);
786         VK_CHECK(vk.bindImageMemory(vkDevice, *m_drawResources[resourceNdx].depthStencilImage,
787                                     m_drawResources[resourceNdx].depthStencilImageAlloc->getMemory(),
788                                     m_drawResources[resourceNdx].depthStencilImageAlloc->getOffset()));
789 
790         // Create image view.
791         const VkImageViewCreateInfo imageViewParams = {
792             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,        // VkStructureType            sType
793             nullptr,                                         // const void*                pNext
794             0u,                                              // VkImageViewCreateFlags    flags
795             *m_drawResources[resourceNdx].depthStencilImage, // VkImage                    image
796             VK_IMAGE_VIEW_TYPE_2D,                           // VkImageViewType            viewType
797             m_testParams.depthStencilFormat,                 // VkFormat                    format
798             componentMappingIdentity,                        // VkChannelMapping            channels
799             {aspectFlags, 0u, 1u, 0u, 1u}                    // VkImageSubresourceRange    subresourceRange
800         };
801         m_drawResources[resourceNdx].depthStencilImageView = createImageView(vk, vkDevice, &imageViewParams);
802 
803         // Clear and transition image to desired layout for easier looping later when rendering.
804         {
805             const auto dstAccess =
806                 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
807             const auto dstStage =
808                 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
809             const auto layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
810 
811             clearDepthStencilImage(vk, vkDevice, queue, queueFamilyIndex,
812                                    *m_drawResources[resourceNdx].depthStencilImage, m_testParams.depthStencilFormat,
813                                    m_testParams.depthClearValue, m_testParams.stencilClearValue,
814                                    VK_IMAGE_LAYOUT_UNDEFINED, layout, dstAccess, dstStage);
815         }
816     }
817 
818     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
819         createRenderPassFramebuffer<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
820                                     RenderPassCreateInfo1>(useDithering);
821     else if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
822         createRenderPassFramebuffer<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
823                                     RenderPassCreateInfo2>(useDithering);
824 
825     // Pipeline.
826     {
827         const VkVertexInputBindingDescription vertexInputBindingDescription = {
828             0u,                            // uint32_t                    binding
829             (uint32_t)sizeof(Vertex4RGBA), // uint32_t                    strideInBytes
830             VK_VERTEX_INPUT_RATE_VERTEX    // VkVertexInputStepRate    inputRate
831         };
832 
833         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
834             {
835                 0u,                            // uint32_t    location
836                 0u,                            // uint32_t    binding
837                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format
838                 0u                             // uint32_t    offset
839             },
840             {
841                 1u,                            // uint32_t    location
842                 0u,                            // uint32_t    binding
843                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format
844                 (uint32_t)(sizeof(float) * 4), // uint32_t    offset
845             }};
846 
847         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
848             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                            sType
849             nullptr,                        // const void*                                pNext
850             0u,                             // VkPipelineVertexInputStateCreateFlags    flags
851             1u,                             // uint32_t                                    vertexBindingDescriptionCount
852             &vertexInputBindingDescription, // const VkVertexInputBindingDescription*    pVertexBindingDescriptions
853             2u, // uint32_t                                    vertexAttributeDescriptionCount
854             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
855         };
856 
857         const VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags    colorWriteMask
858                                                 | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
859                                                 VK_COLOR_COMPONENT_A_BIT;
860 
861         std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
862         for (uint32_t i = 0u; i < colorFormats.size(); ++i)
863         {
864             const VkPipelineColorBlendAttachmentState blendState = {
865                 m_testParams.blending ? VK_TRUE : VK_FALSE, // VkBool32                    blendEnable
866                 m_testParams.srcFactor,                     // VkBlendFactor            srcColorBlendFactor
867                 m_testParams.dstFactor,                     // VkBlendFactor            dstColorBlendFactor
868                 VK_BLEND_OP_ADD,                            // VkBlendOp                colorBlendOp
869                 VK_BLEND_FACTOR_ONE,                        // VkBlendFactor            srcAlphaBlendFactor
870                 VK_BLEND_FACTOR_ZERO,                       // VkBlendFactor            dstAlphaBlendFactor
871                 VK_BLEND_OP_ADD,                            // VkBlendOp                alphaBlendOp
872                 writeMask                                   // VkColorComponentFlags    colorWriteMask
873             };
874             colorBlendAttachmentStates.emplace_back(blendState);
875         }
876 
877         const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
878             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
879             nullptr,           // const void*                                    pNext
880             0u,                // VkPipelineColorBlendStateCreateFlags            flags
881             VK_FALSE,          // VkBool32                                        logicOpEnable
882             VK_LOGIC_OP_CLEAR, // VkLogicOp                                    logicOp
883             (uint32_t)
884                 colorBlendAttachmentStates.size(), // uint32_t                                        attachmentCount
885             colorBlendAttachmentStates.data(),     // const VkPipelineColorBlendAttachmentState*    pAttachments
886             {0.0f, 0.0f, 0.0f, 0.0f}               // float                                        blendConstants[4]
887         };
888 
889         const bool useDepthStencil            = (m_testParams.depthStencilFormat != VK_FORMAT_UNDEFINED);
890         const VkStencilOpState stencilOpState = {
891             VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
892             VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
893             VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
894             VK_COMPARE_OP_EQUAL, // VkCompareOp compareOp;
895             0xff,                // uint32_t compareMask;
896             0xff,                // uint32_t writeMask;
897             0x81                 // uint32_t reference;
898         };
899         const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = {
900             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                            sType
901             nullptr,                              // const void*                                pNext
902             0u,                                   // VkPipelineDepthStencilStateCreateFlags    flags
903             useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32                                    depthTestEnable
904             useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32                                    depthWriteEnable
905             m_testParams.depthCompareOp,          // VkCompareOp                                depthCompareOp
906             VK_FALSE,                             // VkBool32                                    depthBoundsTestEnable
907             useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32                                    stencilTestEnable
908             stencilOpState,                       // VkStencilOpState                            front
909             stencilOpState,                       // VkStencilOpState                            back
910             0.0f,                                 // float                                    minDepthBounds
911             1.0f,                                 // float                                    maxDepthBounds
912         };
913 
914         const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
915             VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                            sType
916             nullptr,               // const void*                                pNext
917             0u,                    // VkPipelineMultisampleStateCreateFlags    flags
918             VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits                    rasterizationSamples
919             VK_FALSE,              // VkBool32                                    sampleShadingEnable
920             1.0f,                  // float                                    minSampleShading
921             nullptr,               // const VkSampleMask*                        pSampleMask
922             VK_FALSE,              // VkBool32                                    alphaToCoverageEnable
923             VK_FALSE               // VkBool32                                    alphaToOneEnable
924         };
925 
926         const VkDynamicState dynamicState = VK_DYNAMIC_STATE_VIEWPORT;
927 
928         const VkPipelineDynamicStateCreateInfo dynamicStateParams = {
929             VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
930             nullptr,                                              // const void* pNext;
931             0u,                                                   // VkPipelineDynamicStateCreateFlags flags;
932             1u,                                                   // uint32_t dynamicStateCount;
933             &dynamicState                                         // const VkDynamicState* pDynamicStates;
934         };
935 
936         VkPipelineRenderingCreateInfoKHR renderingCreateInfo = {VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
937                                                                 nullptr,
938                                                                 0u,
939                                                                 0u,
940                                                                 nullptr,
941                                                                 VK_FORMAT_UNDEFINED,
942                                                                 VK_FORMAT_UNDEFINED};
943 
944         VkPipelineCreateFlags2CreateInfoKHR pipelineCreateFlags2Info = {
945             VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR, nullptr,
946             VK_PIPELINE_CREATE_2_ENABLE_LEGACY_DITHERING_BIT_EXT};
947 
948         void *nextPtr = nullptr;
949         if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
950         {
951             renderingCreateInfo.colorAttachmentCount    = (uint32_t)(colorFormats.size());
952             renderingCreateInfo.pColorAttachmentFormats = colorFormats.data();
953 
954             if (useDepthStencil)
955             {
956                 renderingCreateInfo.depthAttachmentFormat   = m_testParams.depthStencilFormat;
957                 renderingCreateInfo.stencilAttachmentFormat = m_testParams.depthStencilFormat;
958             }
959 
960             nextPtr = &renderingCreateInfo;
961 
962             if (m_testParams.revision2)
963             {
964                 pipelineCreateFlags2Info.pNext = nextPtr;
965                 nextPtr                        = &pipelineCreateFlags2Info;
966             }
967         }
968 
969         const std::vector<VkViewport> viewports(1u, makeViewport(imageSize));
970         const std::vector<VkRect2D> scissors(1u, makeRect2D(imageSize));
971 
972         m_drawResources[resourceNdx].pipeline = makeGraphicsPipeline(
973             vk,                      // const DeviceInterface&                            vk
974             vkDevice,                // const VkDevice                                    device
975             *m_pipelineLayout,       // const VkPipelineLayout                            pipelineLayout
976             *m_vertexShaderModule,   // const VkShaderModule                                vertexShaderModule
977             VK_NULL_HANDLE,          // const VkShaderModule                                tessellationControlModule
978             VK_NULL_HANDLE,          // const VkShaderModule                                tessellationEvalModule
979             VK_NULL_HANDLE,          // const VkShaderModule                                geometryShaderModule
980             *m_fragmentShaderModule, // const VkShaderModule                                fragmentShaderModule
981             *m_drawResources[resourceNdx].renderPass, // const VkRenderPass                                renderPass
982             viewports,                                // const std::vector<VkViewport>&                    viewports
983             scissors,                                 // const std::vector<VkRect2D>&                        scissors
984             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,      // const VkPrimitiveTopology                        topology
985             0u,                                       // const uint32_t                                    subpass
986             0u,                       // const uint32_t                                    patchControlPoints
987             &vertexInputStateParams,  // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
988             nullptr,                  // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
989             &multisampleStateParams,  // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
990             &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
991             &colorBlendStateParams,   // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
992             &dynamicStateParams,      // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
993             nextPtr);                 // const void*                                        pNext
994     }
995 }
996 
997 template <typename AttachmentDescription, typename AttachmentReference, typename SubpassDescription,
998           typename RenderPassCreateInfo>
createRenderPassFramebuffer(bool useDithering)999 void DitheringTestInstance::createRenderPassFramebuffer(bool useDithering)
1000 {
1001     const DeviceInterface &vk = m_context.getDeviceInterface();
1002     const VkDevice vkDevice   = getDevice(m_context);
1003 
1004     uint32_t resourceNdx               = useDithering ? m_ditheringNdx : m_noDitheringNdx;
1005     std::vector<VkFormat> colorFormats = m_testParams.colorFormats;
1006     const tcu::UVec2 &imageSize        = m_testParams.imageSize;
1007 
1008     std::vector<AttachmentDescription> attachmentDescriptions;
1009     std::vector<AttachmentReference> attachmentReferences;
1010 
1011     for (uint32_t i = 0u; i < colorFormats.size(); ++i)
1012     {
1013         const AttachmentDescription attachmentDesc = {
1014             nullptr,                                  // const void*                        pNext
1015             (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFlags        flags
1016             colorFormats[i],                          // VkFormat                            format
1017             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits            samples
1018             VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp                loadOp
1019             VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp                storeOp
1020             VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp                stencilLoadOp
1021             VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp                stencilStoreOp
1022             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                    initialLayout
1023             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL      // VkImageLayout                    finalLayout
1024         };
1025 
1026         const AttachmentReference attachmentReference = {
1027             nullptr,                                  // const void*            pNext
1028             i,                                        // uint32_t                attachment
1029             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
1030             VK_IMAGE_ASPECT_COLOR_BIT                 // VkImageAspectFlags    aspectMask
1031         };
1032 
1033         attachmentDescriptions.emplace_back(attachmentDesc);
1034         attachmentReferences.emplace_back(attachmentReference);
1035     }
1036 
1037     bool useDepthStencil                      = (m_testParams.depthStencilFormat != VK_FORMAT_UNDEFINED);
1038     const AttachmentDescription dsDescription = {
1039         nullptr,                                          // const void*                        pNext
1040         (VkAttachmentDescriptionFlags)0,                  // VkAttachmentDescriptionFlags        flags
1041         m_testParams.depthStencilFormat,                  // VkFormat                            format
1042         VK_SAMPLE_COUNT_1_BIT,                            // VkSampleCountFlagBits            samples
1043         VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp                loadOp
1044         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp                storeOp
1045         VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp                stencilLoadOp
1046         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp                stencilStoreOp
1047         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout                    initialLayout
1048         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL              // VkImageLayout                    finalLayout
1049     };
1050     const AttachmentReference dsReference = {
1051         nullptr,                                                // const void*            pNext
1052         (uint32_t)attachmentReferences.size(),                  // uint32_t                attachment
1053         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout        layout
1054         VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT // VkImageAspectFlags    aspectMask
1055     };
1056 
1057     if (useDepthStencil)
1058         attachmentDescriptions.emplace_back(dsDescription);
1059 
1060     VkSubpassDescriptionFlags subpassDescriptionFlags = 0u;
1061     if (useDithering)
1062         subpassDescriptionFlags = VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT;
1063     const SubpassDescription subpassDescription = {
1064         nullptr,
1065         subpassDescriptionFlags,                  // VkSubpassDescriptionFlags        flags
1066         VK_PIPELINE_BIND_POINT_GRAPHICS,          // VkPipelineBindPoint                pipelineBindPoint
1067         0u,                                       // uint32_t                            viewMask
1068         0u,                                       // uint32_t                            inputAttachmentCount
1069         nullptr,                                  // const VkAttachmentReference*        pInputAttachments
1070         (uint32_t)attachmentReferences.size(),    // uint32_t                            colorAttachmentCount
1071         attachmentReferences.data(),              // const VkAttachmentReference*        pColorAttachments
1072         nullptr,                                  // const VkAttachmentReference*        pResolveAttachments
1073         useDepthStencil ? &dsReference : nullptr, // const VkAttachmentReference*        pDepthStencilAttachment
1074         0u,                                       // uint32_t                            preserveAttachmentCount
1075         nullptr                                   // const uint32_t*                    pPreserveAttachments
1076     };
1077 
1078     // Create render pass.
1079     const RenderPassCreateInfo renderPassInfo = {
1080         nullptr,                                 // const void*                        pNext
1081         (VkRenderPassCreateFlags)0,              // VkRenderPassCreateFlags            flags
1082         (uint32_t)attachmentDescriptions.size(), // uint32_t                            attachmentCount
1083         attachmentDescriptions.data(),           // const VkAttachmentDescription*    pAttachments
1084         1,                                       // uint32_t                            subpassCount
1085         &subpassDescription,                     // const VkSubpassDescription*        pSubpasses
1086         0u,                                      // uint32_t                            dependencyCount
1087         nullptr,                                 // const VkSubpassDependency*        pDependencies
1088         0u,                                      // uint32_t                            correlatedViewMaskCount
1089         nullptr                                  // const uint32_t*                    pCorrelatedViewMasks
1090     };
1091 
1092     m_drawResources[resourceNdx].renderPass = renderPassInfo.createRenderPass(vk, vkDevice);
1093 
1094     std::vector<VkImageView> views;
1095     for (const auto &view : m_drawResources[resourceNdx].imageViews)
1096         views.emplace_back(*view);
1097 
1098     if (useDepthStencil)
1099         views.emplace_back(*m_drawResources[resourceNdx].depthStencilImageView);
1100 
1101     // Create framebuffer.
1102     const VkFramebufferCreateInfo framebufferParams = {
1103         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType            sType
1104         nullptr,                                   // const void*                pNext
1105         0u,                                        // VkFramebufferCreateFlags    flags
1106         *m_drawResources[resourceNdx].renderPass,  // VkRenderPass                renderPass
1107         (uint32_t)views.size(),                    // uint32_t                    attachmentCount
1108         views.data(),                              // const VkImageView*        pAttachments
1109         (uint32_t)imageSize.x(),                   // uint32_t                    width
1110         (uint32_t)imageSize.y(),                   // uint32_t                    height
1111         1u                                         // uint32_t                    layers
1112     };
1113 
1114     m_drawResources[resourceNdx].framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1115 }
1116 
1117 } // namespace
1118 
createChildren(tcu::TestCaseGroup * ditheringTests,const SharedGroupParams groupParams,bool revision2)1119 static void createChildren(tcu::TestCaseGroup *ditheringTests, const SharedGroupParams groupParams, bool revision2)
1120 {
1121     tcu::TestContext &testCtx           = ditheringTests->getTestContext();
1122     uint32_t imageDimensions            = 256u;
1123     uint32_t smallRenderAreaDimensions  = 31u;
1124     uint32_t maxRenderOffset            = imageDimensions - smallRenderAreaDimensions;
1125     uint32_t extraRandomAreaRenderCount = 10u;
1126     TestParams testParams;
1127     VkFormat testFormats[] = {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1128                               VK_FORMAT_R5G5B5A1_UNORM_PACK16};
1129     uint32_t testFormatCount = sizeof(testFormats) / sizeof(testFormats[0]);
1130 
1131     testParams.overrideColor      = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f);
1132     testParams.imageSize          = tcu::UVec2{imageDimensions, imageDimensions};
1133     testParams.groupParams        = groupParams;
1134     testParams.depthStencilFormat = VK_FORMAT_UNDEFINED;
1135     testParams.srcFactor          = VK_BLEND_FACTOR_SRC_ALPHA;
1136     testParams.dstFactor          = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
1137     testParams.depthClearValue    = 1.0f;
1138     testParams.stencilClearValue  = 0x81;
1139     testParams.depthCompareOp     = VK_COMPARE_OP_LESS;
1140     testParams.blending           = false;
1141     testParams.revision2          = revision2;
1142 
1143     // Complete render pass.
1144     testParams.renderAreas.emplace_back(makeViewport(testParams.imageSize));
1145 
1146     // Base tests. Ensures dithering works and values are within one ULP.
1147     {
1148         // Test dithering works and values are withing one ULP
1149         de::MovePtr<tcu::TestCaseGroup> baseTests(new tcu::TestCaseGroup(testCtx, "base"));
1150 
1151         // Small render area, snapped to each side (Left, Right, Bottom, Top).
1152         testParams.renderAreas.emplace_back(
1153             makeViewport(0.0f, 99.0f, (float)smallRenderAreaDimensions, (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1154         testParams.renderAreas.emplace_back(makeViewport((float)maxRenderOffset, 99.0f,
1155                                                          (float)smallRenderAreaDimensions,
1156                                                          (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1157         testParams.renderAreas.emplace_back(
1158             makeViewport(99.0f, 0.0f, (float)smallRenderAreaDimensions, (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1159         testParams.renderAreas.emplace_back(makeViewport(99.0f, (float)maxRenderOffset,
1160                                                          (float)smallRenderAreaDimensions,
1161                                                          (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1162 
1163         // Small render area, snapped to each corner (BotLeft, BotRight, TopLeft, TopRight).
1164         testParams.renderAreas.emplace_back(
1165             makeViewport(0.0f, 0.0f, (float)smallRenderAreaDimensions, (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1166         testParams.renderAreas.emplace_back(makeViewport((float)maxRenderOffset, 0.0f, (float)smallRenderAreaDimensions,
1167                                                          (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1168         testParams.renderAreas.emplace_back(makeViewport(0.0f, (float)maxRenderOffset, (float)smallRenderAreaDimensions,
1169                                                          (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1170         testParams.renderAreas.emplace_back(makeViewport((float)maxRenderOffset, (float)maxRenderOffset,
1171                                                          (float)smallRenderAreaDimensions,
1172                                                          (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1173 
1174         // Some random offsets.
1175         srand(uint32_t(time(nullptr)));
1176         for (uint32_t i = 0; i < extraRandomAreaRenderCount; ++i)
1177         {
1178             uint32_t x_offset = ((uint32_t)rand()) % (maxRenderOffset - 1);
1179             uint32_t y_offset = ((uint32_t)rand()) % (maxRenderOffset - 1);
1180 
1181             // Ensure odd offset
1182             x_offset |= 1u;
1183             y_offset |= 1u;
1184 
1185             testParams.renderAreas.emplace_back(makeViewport((float)x_offset, (float)y_offset,
1186                                                              (float)smallRenderAreaDimensions,
1187                                                              (float)smallRenderAreaDimensions, 0.0f, 1.0f));
1188         }
1189 
1190         for (uint32_t i = 0; i < testFormatCount; ++i)
1191         {
1192             testParams.colorFormats.emplace_back(testFormats[i]);
1193             const std::string iFormatName =
1194                 de::toLower(de::toString(getFormatStr(testParams.colorFormats.back())).substr(10));
1195             baseTests->addChild(new DitheringTest(testCtx, iFormatName, testParams));
1196 
1197             for (uint32_t j = i + 1; j < testFormatCount; ++j)
1198             {
1199                 testParams.colorFormats.emplace_back(testFormats[j]);
1200                 const std::string jFormatName =
1201                     iFormatName + "_and_" +
1202                     de::toLower(de::toString(getFormatStr(testParams.colorFormats.back())).substr(10));
1203                 baseTests->addChild(new DitheringTest(testCtx, jFormatName, testParams));
1204 
1205                 for (uint32_t k = j + 1; k < testFormatCount; ++k)
1206                 {
1207                     testParams.colorFormats.emplace_back(testFormats[k]);
1208                     const std::string kFormatName =
1209                         jFormatName + "_and_" +
1210                         de::toLower(de::toString(getFormatStr(testParams.colorFormats.back())).substr(10));
1211                     baseTests->addChild(new DitheringTest(testCtx, kFormatName, testParams));
1212 
1213                     testParams.colorFormats.pop_back();
1214                 }
1215 
1216                 testParams.colorFormats.pop_back();
1217             }
1218 
1219             testParams.colorFormats.pop_back();
1220         }
1221 
1222         ditheringTests->addChild(baseTests.release());
1223     }
1224 
1225     // Complete render pass.
1226     testParams.renderAreas.clear(); // Need to reset all
1227     testParams.renderAreas.emplace_back(makeViewport(testParams.imageSize));
1228 
1229     // Depth/stencil tests. Ensure dithering works with depth/stencil and it does not affect depth/stencil.
1230     {
1231         de::MovePtr<tcu::TestCaseGroup> depthStencilTests(new tcu::TestCaseGroup(testCtx, "depth_stencil"));
1232 
1233         const std::string names[]         = {"Less", "Greater", "Equal"};
1234         const uint32_t stencilValues[]    = {0x80, 0x82, 0x81};
1235         const uint32_t stencilValuesCount = sizeof(stencilValues) / sizeof(stencilValues[0]);
1236         const float *basePtr              = reinterpret_cast<const float *>(&baseDepthValue);
1237         const float *oneUlpMorePtr        = reinterpret_cast<const float *>(&oneUlpMoreDepthValue);
1238         const float *oneUlpLessPtr        = reinterpret_cast<const float *>(&oneUlpLessDepthValue);
1239         const float depthValues[]         = {*oneUlpLessPtr, *oneUlpMorePtr, *basePtr};
1240         const uint32_t depthValuesCount   = sizeof(depthValues) / sizeof(depthValues[0]);
1241         const VkCompareOp compareOps[]    = {VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER};
1242         const uint32_t compareOpsCount    = sizeof(compareOps) / sizeof(compareOps[0]);
1243 
1244         testParams.depthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1245         for (uint32_t i = 0; i < testFormatCount; ++i)
1246         {
1247             testParams.colorFormats.emplace_back(testFormats[i]);
1248             const std::string formatName =
1249                 de::toLower(de::toString(getFormatStr(testParams.colorFormats.back())).substr(10));
1250 
1251             for (uint32_t j = 0u; j < stencilValuesCount; ++j)
1252             {
1253                 testParams.stencilClearValue = stencilValues[j];
1254 
1255                 for (uint32_t k = 0u; k < depthValuesCount; ++k)
1256                 {
1257                     testParams.depthClearValue = depthValues[k];
1258 
1259                     for (uint32_t l = 0u; l < compareOpsCount; ++l)
1260                     {
1261                         testParams.depthCompareOp = compareOps[l];
1262                         depthStencilTests->addChild(new DitheringTest(
1263                             testCtx, "stencil" + names[j] + "_depth" + names[k] + "_op" + names[l] + "_" + formatName,
1264                             testParams));
1265                     }
1266                 }
1267             }
1268             testParams.colorFormats.pop_back();
1269         }
1270         testParams.depthStencilFormat = VK_FORMAT_UNDEFINED;
1271 
1272         ditheringTests->addChild(depthStencilTests.release());
1273     }
1274 
1275     // Blend tests. Ensure dithering works with blending.
1276     {
1277         de::MovePtr<tcu::TestCaseGroup> blendTests(new tcu::TestCaseGroup(testCtx, "blend"));
1278 
1279         testParams.blending = true;
1280         for (uint32_t i = 0; i < testFormatCount; ++i)
1281         {
1282             testParams.colorFormats.emplace_back(testFormats[i]);
1283             const std::string formatName =
1284                 de::toLower(de::toString(getFormatStr(testParams.colorFormats.back())).substr(10));
1285 
1286             testParams.overrideColor = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f);
1287             testParams.srcFactor     = VK_BLEND_FACTOR_SRC_ALPHA;
1288             testParams.dstFactor     = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
1289             blendTests->addChild(new DitheringTest(testCtx, "srcAlpha_" + formatName, testParams));
1290 
1291             testParams.overrideColor = tcu::Vec4(0.125f, 0.0f, 0.0f, 1.0f);
1292             testParams.srcFactor     = VK_BLEND_FACTOR_ONE;
1293             testParams.dstFactor     = VK_BLEND_FACTOR_ONE;
1294             blendTests->addChild(new DitheringTest(testCtx, "additive_" + formatName, testParams));
1295             testParams.colorFormats.pop_back();
1296         }
1297         testParams.blending = false;
1298 
1299         ditheringTests->addChild(blendTests.release());
1300     }
1301 }
1302 
cleanupGroup(tcu::TestCaseGroup * group,const SharedGroupParams,bool revision2)1303 static void cleanupGroup(tcu::TestCaseGroup *group, const SharedGroupParams, bool revision2)
1304 {
1305     DE_UNREF(group);
1306     DE_UNREF(revision2);
1307     // Destroy singleton objects.
1308     g_singletonDevice.clear();
1309 }
1310 
createDitheringRevision1GroupTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1311 static tcu::TestCaseGroup *createDitheringRevision1GroupTests(tcu::TestContext &testCtx,
1312                                                               const SharedGroupParams groupParams)
1313 {
1314     return createTestGroup(testCtx, "v1", createChildren, groupParams, false, cleanupGroup);
1315 }
1316 
createDitheringRevision2GroupTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1317 static tcu::TestCaseGroup *createDitheringRevision2GroupTests(tcu::TestContext &testCtx,
1318                                                               const SharedGroupParams groupParams)
1319 {
1320     return createTestGroup(testCtx, "v2", createChildren, groupParams, true, cleanupGroup);
1321 }
1322 
createRenderPassDitheringTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1323 tcu::TestCaseGroup *createRenderPassDitheringTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
1324 {
1325     // Tests for VK_EXT_legacy_dithering
1326     de::MovePtr<tcu::TestCaseGroup> ditheringTests(new tcu::TestCaseGroup(testCtx, "dithering"));
1327     ditheringTests->addChild(createDitheringRevision1GroupTests(testCtx, groupParams));
1328     if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1329         ditheringTests->addChild(createDitheringRevision2GroupTests(testCtx, groupParams));
1330 
1331     return ditheringTests.release();
1332 }
1333 
1334 } // namespace renderpass
1335 } // namespace vkt
1336