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