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