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