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