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