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