• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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