• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Valve Corporation.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief EXT_discard_rectangles tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawDiscardRectanglesTests.hpp"
26 
27 #include "vkDefs.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vktTestGroupUtil.hpp"
37 #include "vktTestCase.hpp"
38 #include "vktDrawBufferObjectUtil.hpp"
39 #include "vktDrawImageObjectUtil.hpp"
40 
41 #include "tcuTestCase.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 
47 #include "deUniquePtr.hpp"
48 #include "deSharedPtr.hpp"
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 
55 namespace
56 {
57 using namespace vk;
58 using de::UniquePtr;
59 using de::SharedPtr;
60 using de::MovePtr;
61 using tcu::Vec4;
62 using tcu::Vec2;
63 using tcu::UVec2;
64 using tcu::UVec4;
65 
66 enum TestMode
67 {
68 	TEST_MODE_INCLUSIVE = 0,
69 	TEST_MODE_EXCLUSIVE,
70 	TEST_MODE_COUNT
71 };
72 
73 enum TestScissorMode
74 {
75 	TEST_SCISSOR_MODE_NONE = 0,
76 	TEST_SCISSOR_MODE_STATIC,
77 	TEST_SCISSOR_MODE_DYNAMIC,
78 	TEST_SCISSOR_MODE_COUNT
79 };
80 
81 #define NUM_RECT_TESTS 6
82 #define NUM_DYNAMIC_DISCARD_TYPE_TESTS 2
83 
84 struct TestParams
85 {
86 	TestMode		testMode;
87 	deUint32		numRectangles;
88 	deBool			dynamicDiscardRectangles;
89 	TestScissorMode	scissorMode;
90 	deBool			useDynamicRendering;
91 };
92 
93 template<typename T>
sizeInBytes(const std::vector<T> & vec)94 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
95 {
96 	return vec.size() * sizeof(vec[0]);
97 }
98 
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)99 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
100 {
101 	const VkImageCreateInfo imageParams =
102 	{
103 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
104 		DE_NULL,										// const void*				pNext;
105 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
106 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
107 		format,											// VkFormat					format;
108 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
109 		1u,												// deUint32					mipLevels;
110 		1u,												// deUint32					arrayLayers;
111 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
112 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
113 		usage,											// VkImageUsageFlags		usage;
114 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
115 		0u,												// deUint32					queueFamilyIndexCount;
116 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
117 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
118 	};
119 	return imageParams;
120 }
121 
makeDiscardRectangleStateCreateInfo(const deBool dynamicDiscardRectangle,const VkDiscardRectangleModeEXT discardRectangleMode,const deUint32 discardRectangleCount,const VkRect2D * pDiscardRectangles)122 VkPipelineDiscardRectangleStateCreateInfoEXT makeDiscardRectangleStateCreateInfo (const deBool						dynamicDiscardRectangle,
123 																				  const VkDiscardRectangleModeEXT	discardRectangleMode,
124 																				  const deUint32					discardRectangleCount,
125 																				  const VkRect2D					*pDiscardRectangles)
126 {
127 	const VkPipelineDiscardRectangleStateCreateInfoEXT discardRectanglesCreateInfo =
128 	{
129 		VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT,		// VkStructureType									sType;
130 		DE_NULL,																// const void*										pNext;
131 		0u,																		// VkPipelineDiscardRectangleStateCreateFlagsEXT	flags;
132 		discardRectangleMode,													// VkDiscardRectangleModeEXT						discardRectangleMode;
133 		discardRectangleCount,													// deUint32											discardRectangleCount;
134 		dynamicDiscardRectangle ? DE_NULL : pDiscardRectangles					// const VkRect2D*									pDiscardRectangles;
135 	};
136 	return discardRectanglesCreateInfo;
137 }
138 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const deBool dynamicDiscardRectangle,const VkDiscardRectangleModeEXT discardRectangleMode,const deUint32 discardRectangleCount,const VkRect2D * pDiscardRectangles,const TestScissorMode scissorMode,const VkRect2D rectScissor)139 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&			vk,
140 									   const VkDevice					device,
141 									   const VkPipelineLayout			pipelineLayout,
142 									   const VkRenderPass				renderPass,
143 									   const VkShaderModule				vertexModule,
144 									   const VkShaderModule				fragmentModule,
145 									   const UVec2						renderSize,
146 									   const deBool						dynamicDiscardRectangle,
147 									   const VkDiscardRectangleModeEXT	discardRectangleMode,
148 									   const deUint32					discardRectangleCount,
149 									   const VkRect2D*					pDiscardRectangles,
150 									   const TestScissorMode			scissorMode,
151 									   const VkRect2D					rectScissor)
152 {
153 	const VkVertexInputBindingDescription vertexInputBindingDescription =
154 	{
155 		0u,								// uint32_t				binding;
156 		sizeof(Vec4),					// uint32_t				stride;
157 		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
158 	};
159 
160 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
161 	{
162 		{
163 			0u,								// uint32_t			location;
164 			0u,								// uint32_t			binding;
165 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
166 			0u,								// uint32_t			offset;
167 		},
168 	};
169 
170 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
171 	{
172 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType;
173 		DE_NULL,														// const void*									pNext;
174 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags		flags;
175 		1u,																// uint32_t										vertexBindingDescriptionCount;
176 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
177 		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t										vertexAttributeDescriptionCount;
178 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions;
179 	};
180 
181 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
182 	{
183 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType								sType;
184 		DE_NULL,														// const void*									pNext;
185 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags		flags;
186 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,							// VkPrimitiveTopology							topology;
187 		VK_FALSE,														// VkBool32										primitiveRestartEnable;
188 	};
189 
190 
191 	VkViewport		viewport				= makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
192 	const VkRect2D	rectScissorRenderSize	= { { 0, 0 }, { renderSize.x(), renderSize.y() } };
193 
194 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
195 	{
196 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,							// VkStructureType								sType;
197 		DE_NULL,																		// const void*									pNext;
198 		(VkPipelineViewportStateCreateFlags)0,											// VkPipelineViewportStateCreateFlags			flags;
199 		1u,																				// uint32_t										viewportCount;
200 		&viewport,																		// const VkViewport*							pViewports;
201 		1u,																				// uint32_t										scissorCount;
202 		scissorMode != TEST_SCISSOR_MODE_NONE ? &rectScissor : &rectScissorRenderSize,	// const VkRect2D*								pScissors;
203 	};
204 
205 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
206 	{
207 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType								sType;
208 		DE_NULL,														// const void*									pNext;
209 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags		flags;
210 		VK_FALSE,														// VkBool32										depthClampEnable;
211 		VK_FALSE,														// VkBool32										rasterizerDiscardEnable;
212 		VK_POLYGON_MODE_FILL,											// VkPolygonMode								polygonMode;
213 		VK_CULL_MODE_NONE,												// VkCullModeFlags								cullMode;
214 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace									frontFace;
215 		VK_FALSE,														// VkBool32										depthBiasEnable;
216 		0.0f,															// float										depthBiasConstantFactor;
217 		0.0f,															// float										depthBiasClamp;
218 		0.0f,															// float										depthBiasSlopeFactor;
219 		1.0f,															// float										lineWidth;
220 	};
221 
222 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
223 	{
224 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType								sType;
225 		DE_NULL,														// const void*									pNext;
226 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags		flags;
227 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits						rasterizationSamples;
228 		VK_FALSE,														// VkBool32										sampleShadingEnable;
229 		0.0f,															// float										minSampleShading;
230 		DE_NULL,														// const VkSampleMask*							pSampleMask;
231 		VK_FALSE,														// VkBool32										alphaToCoverageEnable;
232 		VK_FALSE														// VkBool32										alphaToOneEnable;
233 	};
234 
235 	const VkStencilOpState stencilOpState = makeStencilOpState(
236 		VK_STENCIL_OP_KEEP,				// stencil fail
237 		VK_STENCIL_OP_KEEP,				// depth & stencil pass
238 		VK_STENCIL_OP_KEEP,				// depth only fail
239 		VK_COMPARE_OP_ALWAYS,			// compare op
240 		0u,								// compare mask
241 		0u,								// write mask
242 		0u);							// reference
243 
244 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
245 	{
246 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType								sType;
247 		DE_NULL,														// const void*									pNext;
248 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags		flags;
249 		VK_FALSE,														// VkBool32										depthTestEnable;
250 		VK_FALSE,														// VkBool32										depthWriteEnable;
251 		VK_COMPARE_OP_LESS,												// VkCompareOp									depthCompareOp;
252 		VK_FALSE,														// VkBool32										depthBoundsTestEnable;
253 		VK_FALSE,														// VkBool32										stencilTestEnable;
254 		stencilOpState,													// VkStencilOpState								front;
255 		stencilOpState,													// VkStencilOpState								back;
256 		0.0f,															// float										minDepthBounds;
257 		1.0f,															// float										maxDepthBounds;
258 	};
259 
260 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
261 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
262 	{
263 		VK_FALSE,						// VkBool32					blendEnable;
264 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
265 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
266 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
267 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
268 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
269 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
270 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
271 	};
272 
273 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
274 	{
275 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
276 		DE_NULL,														// const void*									pNext;
277 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
278 		VK_FALSE,														// VkBool32										logicOpEnable;
279 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
280 		1u,																// deUint32										attachmentCount;
281 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
282 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
283 	};
284 
285 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
286 	{
287 		{
288 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType								sType;
289 			DE_NULL,													// const void*									pNext;
290 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags				flags;
291 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits						stage;
292 			vertexModule,												// VkShaderModule								module;
293 			"main",														// const char*									pName;
294 			DE_NULL,													// const VkSpecializationInfo*					pSpecializationInfo;
295 		},
296 		{
297 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType								sType;
298 			DE_NULL,													// const void*									pNext;
299 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags				flags;
300 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits						stage;
301 			fragmentModule,												// VkShaderModule								module;
302 			"main",														// const char*									pName;
303 			DE_NULL,													// const VkSpecializationInfo*					pSpecializationInfo;
304 		},
305 	};
306 
307 	const VkPipelineDiscardRectangleStateCreateInfoEXT discardRectangleStateCreateInfo = makeDiscardRectangleStateCreateInfo(dynamicDiscardRectangle, discardRectangleMode, discardRectangleCount, pDiscardRectangles);
308 
309 	const VkDynamicState dynamicStateDiscardRectangles	= VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT;
310 	const VkDynamicState dynamicStateScissor			= VK_DYNAMIC_STATE_SCISSOR;
311 	std::vector<VkDynamicState> dynamicStates;
312 
313 	if (dynamicDiscardRectangle)
314 		dynamicStates.push_back(dynamicStateDiscardRectangles);
315 	if (scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
316 		dynamicStates.push_back(dynamicStateScissor);
317 
318 	const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo =
319 	{
320 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,			// VkStructureType								sType;
321 		DE_NULL,														// const void*									pNext;
322 		0u,																// VkPipelineDynamicStateCreateFlags			flags;
323 		(deUint32)dynamicStates.size(),									// deUint32										dynamicStateCount;
324 		dynamicStates.data()											// const VkDynamicState*						pDynamicStates;
325 	};
326 
327 	VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
328 	{
329 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,				// VkStructureType									sType;
330 		&discardRectangleStateCreateInfo,								// const void*										pNext;
331 		(VkPipelineCreateFlags)0,										// VkPipelineCreateFlags							flags;
332 		2u,																// deUint32											stageCount;
333 		pShaderStages,													// const VkPipelineShaderStageCreateInfo*			pStages;
334 		&vertexInputStateInfo,											// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
335 		&pipelineInputAssemblyStateInfo,								// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
336 		DE_NULL,														// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
337 		&pipelineViewportStateInfo,										// const VkPipelineViewportStateCreateInfo*			pViewportState;
338 		&pipelineRasterizationStateInfo,								// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
339 		&pipelineMultisampleStateInfo,									// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
340 		&pipelineDepthStencilStateInfo,									// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
341 		&pipelineColorBlendStateInfo,									// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
342 		&pipelineDynamicStateCreateInfo,								// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
343 		pipelineLayout,													// VkPipelineLayout									layout;
344 		renderPass,														// VkRenderPass										renderPass;
345 		0u,																// deUint32											subpass;
346 		DE_NULL,														// VkPipeline										basePipelineHandle;
347 		0,																// deInt32											basePipelineIndex;
348 	};
349 
350 	VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
351 	vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
352 	{
353 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
354 		&discardRectangleStateCreateInfo,
355 		0u,
356 		1u,
357 		&colorAttachmentFormat,
358 		VK_FORMAT_UNDEFINED,
359 		VK_FORMAT_UNDEFINED
360 	};
361 
362 	// when pipeline is created without render pass we are using dynamic rendering
363 	if (renderPass == DE_NULL)
364 		graphicsPipelineInfo.pNext = &renderingCreateInfo;
365 
366 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
367 }
368 
generateDiscardRectangles(const UVec2 & renderSize,deUint32 numRect,std::vector<VkRect2D> & rectangles)369 void generateDiscardRectangles(const UVec2& renderSize, deUint32 numRect, std::vector<VkRect2D>& rectangles)
370 {
371 	deUint32 cellHight = renderSize.y() - 10;
372 	deUint32 cellWidth = (renderSize.x() - 10) / (2 * numRect - 1);
373 
374 	DE_ASSERT(rectangles.size() == 0);
375 
376 	for (deUint32 i = 0; i < numRect; i++)
377 	{
378 		VkRect2D rect;
379 		rect.extent.height = cellHight;
380 		rect.extent.width = cellWidth;
381 		rect.offset.x = 5u + i * 2 * cellWidth;
382 		rect.offset.y = 5u;
383 		rectangles.push_back(rect);
384 	}
385 }
386 
387 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const TestMode testMode,const Vec4 & color,const deUint32 numRectangles,const std::vector<VkRect2D> rectangles,const deBool enableScissor,const VkRect2D scissor)388 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat		format,
389 										  const UVec2&					renderSize,
390 										  const TestMode				testMode,
391 										  const Vec4&					color,
392 										  const deUint32				numRectangles,
393 										  const std::vector<VkRect2D>	rectangles,
394 										  const deBool					enableScissor,
395 										  const VkRect2D				scissor)
396 {
397 	tcu::TextureLevel	image(format, renderSize.x(), renderSize.y());
398 	const Vec4			rectColor	= testMode == TEST_MODE_INCLUSIVE ? Vec4(0.0f, 1.0f, 0.0f, 1.0f)	: color;
399 	const Vec4			clearColor	= testMode == TEST_MODE_INCLUSIVE ? color							: Vec4(0.0f, 1.0f, 0.0f, 1.0f);
400 
401 	if (!enableScissor)
402 	{
403 		// Clear the image with clearColor
404 		tcu::clear(image.getAccess(), clearColor);
405 
406 		// Now draw the discard rectangles taking into account the selected mode.
407 		for (deUint32 i = 0; i < numRectangles; i++)
408 		{
409 			tcu::clear(tcu::getSubregion(image.getAccess(), rectangles[i].offset.x, rectangles[i].offset.y,
410 										 rectangles[i].extent.width, rectangles[i].extent.height),
411 					   rectColor);
412 		}
413 	}
414 	else
415 	{
416 		// Clear the image with the original clear color
417 		tcu::clear(image.getAccess(), color);
418 		// Clear the scissor are with the clearColor which depends on the selected mode
419 		tcu::clear(tcu::getSubregion(image.getAccess(), scissor.offset.x, scissor.offset.y,
420 									 scissor.extent.width, scissor.extent.height),
421 				   clearColor);
422 
423 		// Now draw the discard rectangles taking into account both the scissor area and
424 		// the selected mode.
425 		for (deUint32 rect = 0; rect < numRectangles; rect++)
426 		{
427 			for (deUint32 x = rectangles[rect].offset.x; x < (rectangles[rect].offset.x + rectangles[rect].extent.width); x++)
428 			{
429 				for(deUint32 y = rectangles[rect].offset.y; y < (rectangles[rect].offset.y + rectangles[rect].extent.height); y++)
430 				{
431 					if ((x >= (deUint32)scissor.offset.x) && (x < (scissor.offset.x + scissor.extent.width)) &&
432 						(y >= (deUint32)scissor.offset.y) && (y < (scissor.offset.y + scissor.extent.height)))
433 					{
434 						image.getAccess().setPixel(rectColor, x, y);
435 					}
436 				}
437 			}
438 		}
439 	}
440 	return image;
441 }
442 
443 class DiscardRectanglesTestInstance : public TestInstance
444 {
445 public:
446 							DiscardRectanglesTestInstance		(Context& context,
447 																 TestParams params);
~DiscardRectanglesTestInstance(void)448 	virtual					~DiscardRectanglesTestInstance		(void) {}
449 	virtual tcu::TestStatus	iterate								(void);
450 
451 private:
452 	const TestParams			m_params;
453 	const Vec4					m_clearColor;
454 	const UVec2					m_renderSize;
455 	std::vector<Vec4>			m_vertices;
456 	std::vector<VkRect2D>		m_rectangles;
457 
458 	Move<VkImage>				m_colorImage;
459 	MovePtr<Allocation>			m_colorImageAlloc;
460 	Move<VkImageView>			m_colorAttachment;
461 	SharedPtr<Buffer>			m_colorBuffer;
462 	SharedPtr<Buffer>			m_vertexBuffer;
463 	Move<VkShaderModule>		m_vertexModule;
464 	Move<VkShaderModule>		m_fragmentModule;
465 	Move<VkRenderPass>			m_renderPass;
466 	Move<VkFramebuffer>			m_framebuffer;
467 	Move<VkPipelineLayout>		m_pipelineLayout;
468 	Move<VkPipeline>			m_pipeline;
469 	Move<VkCommandPool>			m_cmdPool;
470 	Move<VkCommandBuffer>		m_cmdBuffer;
471 };
472 
DiscardRectanglesTestInstance(Context & context,TestParams params)473 DiscardRectanglesTestInstance::DiscardRectanglesTestInstance (Context& context,
474 															  TestParams params)
475 	: TestInstance	(context)
476 	, m_params		(params)
477 	, m_clearColor	(Vec4(1.0f, 0.0f, 0.0f, 1.0f))
478 	, m_renderSize	(UVec2(340, 100))
479 {
480 }
481 
iterate(void)482 tcu::TestStatus DiscardRectanglesTestInstance::iterate	(void)
483 {
484 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
485 	const InstanceInterface&		vki						= m_context.getInstanceInterface();
486 	const VkPhysicalDevice			physicalDevice			= m_context.getPhysicalDevice();
487 	const VkDevice					device					= m_context.getDevice();
488 	const VkQueue					queue					= m_context.getUniversalQueue();
489 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
490 	Allocator&						allocator				= m_context.getDefaultAllocator();
491 	const VkDiscardRectangleModeEXT	discardRectangleMode	= m_params.testMode == TEST_MODE_EXCLUSIVE ? VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT : VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
492 	const VkRect2D					rectScissor				= { { 90, 25 }, { 160, 50} };
493 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
494 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
495 	const VkDeviceSize				colorBufferSize			= m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
496 
497 	// Check for VK_EXT_discard_rectangles support and maximum number of active discard rectangles
498 	{
499 		VkPhysicalDeviceDiscardRectanglePropertiesEXT discardRectangleProperties;
500 		deMemset(&discardRectangleProperties, 0, sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT));
501 		discardRectangleProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT;
502 
503 		VkPhysicalDeviceProperties2 physicalDeviceProperties;
504 		physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
505 		physicalDeviceProperties.pNext = &discardRectangleProperties;
506 
507 		vki.getPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties);
508 
509 		if (discardRectangleProperties.maxDiscardRectangles == 0)
510 		{
511 			throw tcu::NotSupportedError("Implementation doesn't support discard rectangles");
512 		}
513 
514 		if (discardRectangleProperties.maxDiscardRectangles < 4)
515 		{
516 			std::ostringstream message;
517 			message << "Implementation doesn't support the minimum value for maxDiscardRectangles: " << discardRectangleProperties.maxDiscardRectangles << " < 4";
518 			return tcu::TestStatus::fail(message.str());
519 		}
520 
521 		if (discardRectangleProperties.maxDiscardRectangles < m_params.numRectangles)
522 		{
523 			std::ostringstream message;
524 			message << "Implementation doesn't support the required number of discard rectangles: " << discardRectangleProperties.maxDiscardRectangles << " < " << m_params.numRectangles;
525 			throw tcu::NotSupportedError(message.str());
526 		}
527 	}
528 
529 	// Color attachment
530 	{
531 		m_colorImage		= makeImage(vk, device, makeImageCreateInfo(colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
532 		m_colorImageAlloc	= bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
533 		m_colorBuffer		= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
534 		m_colorAttachment	= makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
535 
536 		// Zero colorBuffer.
537 		const Allocation alloc = m_colorBuffer->getBoundMemory();
538 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
539 		flushAlloc(vk, device, alloc);
540 	}
541 
542 	// Initialize the pipeline and other variables
543 	{
544 		// Draw a quad covering the whole framebuffer
545 		m_vertices.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
546 		m_vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
547 		m_vertices.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
548 		m_vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
549 		VkDeviceSize vertexBufferSize	= sizeInBytes(m_vertices);
550 		m_vertexBuffer					= Buffer::createAndAlloc	(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
551 
552 
553 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices.data(), static_cast<std::size_t>(vertexBufferSize));
554 		flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
555 
556 		m_vertexModule				= createShaderModule	(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
557 		m_fragmentModule			= createShaderModule	(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
558 
559 		if (!m_params.useDynamicRendering)
560 		{
561 			m_renderPass			= makeRenderPass		(vk, device, colorFormat);
562 			m_framebuffer			= makeFramebuffer		(vk, device, *m_renderPass, m_colorAttachment.get(),
563 															 static_cast<deUint32>(m_renderSize.x()),
564 															 static_cast<deUint32>(m_renderSize.y()));
565 		}
566 
567 		m_pipelineLayout			= makePipelineLayout	(vk, device);
568 
569 		generateDiscardRectangles(m_renderSize, m_params.numRectangles, m_rectangles);
570 		m_pipeline					= makeGraphicsPipeline	(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule, m_renderSize,
571 															 m_params.dynamicDiscardRectangles, discardRectangleMode, m_params.numRectangles,
572 															 m_rectangles.data(), m_params.scissorMode, rectScissor);
573 		m_cmdPool					= createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
574 		m_cmdBuffer					= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
575 	}
576 
577 	// Write command buffer and submit it
578 	{
579 		beginCommandBuffer(vk, *m_cmdBuffer);
580 
581 		const VkClearValue			clearValue	= makeClearValueColor(m_clearColor);
582 		const VkRect2D				renderArea	=
583 		{
584 			makeOffset2D(0, 0),
585 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
586 		};
587 
588 		if (m_params.useDynamicRendering)
589 		{
590 			initialTransitionColor2DImage(vk, *m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
591 										  VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
592 			beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
593 		}
594 		else
595 		{
596 			const VkRenderPassBeginInfo renderPassBeginInfo =
597 			{
598 				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
599 				DE_NULL,										// const void*             pNext;
600 				*m_renderPass,									// VkRenderPass            renderPass;
601 				*m_framebuffer,									// VkFramebuffer           framebuffer;
602 				renderArea,										// VkRect2D                renderArea;
603 				1u,												// uint32_t                clearValueCount;
604 				&clearValue,									// const VkClearValue*     pClearValues;
605 			};
606 			vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
607 		}
608 
609 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
610 		{
611 			const VkBuffer vertexBuffer = m_vertexBuffer->object();
612 			const VkDeviceSize vertexBufferOffset = 0ull;
613 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
614 		}
615 		if (m_params.dynamicDiscardRectangles)
616 		{
617 			vk.cmdSetDiscardRectangleEXT(*m_cmdBuffer, 0u, m_params.numRectangles, m_rectangles.data());
618 		}
619 		if (m_params.scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
620 		{
621 			vk.cmdSetScissor(*m_cmdBuffer, 0u, 1u, &rectScissor);
622 		}
623 		vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u);	// two triangles
624 
625 		if (m_params.useDynamicRendering)
626 			vk.cmdEndRenderingKHR(*m_cmdBuffer);
627 		else
628 			vk.cmdEndRenderPass(*m_cmdBuffer);
629 
630 		copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, m_colorBuffer->object(), tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorSubresourceRange.layerCount);
631 
632 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
633 		submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
634 	}
635 
636 	// Verify results
637 	{
638 		const Allocation alloc = m_colorBuffer->getBoundMemory();
639 		invalidateAlloc(vk, device, alloc);
640 
641 		const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), m_renderSize.x(), m_renderSize.y(), 1u, alloc.getHostPtr());
642 		const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), m_renderSize, m_params.testMode, m_clearColor,
643 																					 m_params.numRectangles, m_rectangles, m_params.scissorMode != TEST_SCISSOR_MODE_NONE, rectScissor);
644 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
645 			TCU_FAIL("Rendered image is not correct");
646 	}
647 	return tcu::TestStatus::pass("OK");
648 }
649 
650 class DiscardRectanglesTestCase : public TestCase
651 {
652 public:
653 								DiscardRectanglesTestCase	(tcu::TestContext &context,
654 															 const char *name,
655 															 const char *description,
656 															 TestParams params);
~DiscardRectanglesTestCase(void)657 	virtual						~DiscardRectanglesTestCase	(void) {}
658 
659 	virtual TestInstance*		createInstance				(Context& context)	const;
660 	virtual void				initPrograms				(SourceCollections& programCollection) const;
661 	virtual void				checkSupport				(Context& context) const;
662 
663 private:
664 	const TestParams			m_params;
665 };
666 
DiscardRectanglesTestCase(tcu::TestContext & context,const char * name,const char * description,TestParams params)667 DiscardRectanglesTestCase::DiscardRectanglesTestCase	(tcu::TestContext &context,
668 														 const char *name,
669 														 const char *description,
670 														 TestParams params)
671 	: TestCase		(context, name, description)
672 	, m_params		(params)
673 {
674 }
675 
initPrograms(SourceCollections & programCollection) const676 void DiscardRectanglesTestCase::initPrograms(SourceCollections& programCollection) const
677 {
678 	// Vertex
679 	{
680 		std::ostringstream src;
681 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
682 			<< "\n"
683 			<< "layout(location = 0) in highp vec4 position;\n"
684 			<< "layout(location = 0) out highp vec4 vsColor;\n"
685 			<< "\n"
686 			<< "out gl_PerVertex {\n"
687 			<< "   vec4 gl_Position;\n"
688 			<< "};\n"
689 			<< "\n"
690 			<< "void main (void)\n"
691 			<< "{\n"
692 			<< "    gl_Position = position;\n"
693 			<< "    vsColor     = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
694 			<< "}\n";
695 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
696 	}
697 
698 	// Fragment
699 	{
700 		std::ostringstream src;
701 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
702 			<< "\n"
703 			<< "layout(location = 0) in highp vec4 vsColor;\n"
704 			<< "layout(location = 0) out highp vec4 fsColor;\n"
705 			<< "\n"
706 			<< "void main (void)\n"
707 			<< "{\n"
708 			<< "    fsColor     = vsColor;\n"
709 			<< "}\n";
710 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
711 	}
712 }
713 
checkSupport(Context & context) const714 void DiscardRectanglesTestCase::checkSupport (Context& context) const
715 {
716 	context.requireDeviceFunctionality("VK_EXT_discard_rectangles");
717 	if (m_params.useDynamicRendering)
718 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
719 }
720 
createInstance(Context & context) const721 TestInstance* DiscardRectanglesTestCase::createInstance (Context& context) const
722 {
723 	return new DiscardRectanglesTestInstance(context, m_params);
724 }
725 
createTests(tcu::TestCaseGroup * testGroup,bool useDynamicRendering)726 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
727 {
728 	tcu::TestContext&	testCtx											= testGroup->getTestContext();
729 	deUint32			numRect [NUM_RECT_TESTS]						= { 1, 2, 3, 4,  8, 16};
730 	std::string			modeName [TEST_MODE_COUNT]						= { "inclusive_", "exclusive_" };
731 	std::string			scissorName [TEST_SCISSOR_MODE_COUNT]			= { "", "scissor_", "dynamic_scissor_" };
732 	std::string			dynamicName [NUM_DYNAMIC_DISCARD_TYPE_TESTS]	= { "", "dynamic_discard_" };
733 
734 	for (deUint32 dynamic = 0 ; dynamic < NUM_DYNAMIC_DISCARD_TYPE_TESTS; dynamic++)
735 	{
736 		for (deUint32 scissor = 0 ; scissor < TEST_SCISSOR_MODE_COUNT; scissor++)
737 		{
738 			for (deUint32 mode = 0; mode < TEST_MODE_COUNT; mode++)
739 			{
740 				for (deUint32 rect = 0; rect < NUM_RECT_TESTS; rect++)
741 				{
742 					std::ostringstream	name;
743 					TestParams			params;
744 
745 					params.testMode						= (TestMode) mode;
746 					params.dynamicDiscardRectangles		= dynamic ? DE_TRUE : DE_FALSE;
747 					params.scissorMode					= (TestScissorMode) scissor;
748 					params.numRectangles				= numRect[rect];
749 					params.useDynamicRendering			= useDynamicRendering;
750 					name << dynamicName[dynamic] << scissorName[scissor] << modeName[mode] << "rect_" << numRect[rect];
751 
752 					testGroup->addChild(new DiscardRectanglesTestCase(testCtx, name.str().c_str(), "", params));
753 				}
754 			}
755 		}
756 	}
757 }
758 }	// Anonymous
759 
createDiscardRectanglesTests(tcu::TestContext & testCtx,bool useDynamicRendering)760 tcu::TestCaseGroup* createDiscardRectanglesTests (tcu::TestContext& testCtx, bool useDynamicRendering)
761 {
762 	return createTestGroup(testCtx, "discard_rectangles", "Discard Rectangles tests", createTests, useDynamicRendering);
763 }
764 
765 }	// Draw
766 }	//vkt
767