• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tests subpass merge feedback extension
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRenderPassSubpassMergeFeedbackTests.hpp"
25 #include "pipeline/vktPipelineImageUtil.hpp"
26 #include "vktTestCase.hpp"
27 #include "vkImageUtil.hpp"
28 #include "vkMemUtil.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuPlatform.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuTestLog.hpp"
42 #include "deStringUtil.hpp"
43 #include "deUniquePtr.hpp"
44 #include "deRandom.hpp"
45 #include <cstring>
46 #include <set>
47 #include <sstream>
48 #include <vector>
49 
50 namespace vkt
51 {
52 namespace renderpass
53 {
54 
55 using namespace vk;
56 
57 namespace
58 {
59 
60 struct TestParams
61 {
62 	deUint32            subpassCount;
63 	bool                disallowMergeRenderpass;
64 	bool                disallowMergeSubPass1;
65 };
66 
67 struct Vertex4RGBA
68 {
69 	tcu::Vec4 position;
70 	tcu::Vec4 color;
71 };
72 
73 class SubpassMergeFeedbackTest : public vkt::TestCase
74 {
75 public:
76 										SubpassMergeFeedbackTest	(tcu::TestContext&	testContext,
77 																     const std::string&	name,
78 																     const std::string&	description,
79 																     const TestParams&	testParams);
80 	virtual								~SubpassMergeFeedbackTest	(void);
81 	virtual TestInstance*				createInstance			(Context&			context) const;
82 private:
83 	const TestParams					m_testParams;
84 };
85 
86 class SubpassMergeFeedbackTestInstance : public vkt::TestInstance
87 {
88 public:
89 										SubpassMergeFeedbackTestInstance	(Context&				context,
90 																		     const TestParams&		testParams);
91 	virtual								~SubpassMergeFeedbackTestInstance	(void);
92 	virtual tcu::TestStatus				iterate							    (void);
93 private:
94 
95 	tcu::TestStatus                     createRenderPassAndVerify           (const DeviceInterface&	vk,
96 																			 VkDevice				vkDevice);
97 
98 	const TestParams					m_testParams;
99 };
100 
SubpassMergeFeedbackTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)101 SubpassMergeFeedbackTest::SubpassMergeFeedbackTest (tcu::TestContext&	testContext,
102 											const std::string&	name,
103 											const std::string&	description,
104 											const TestParams&	testParams)
105 	: vkt::TestCase	(testContext, name, description)
106 	, m_testParams	(testParams)
107 {
108 }
109 
~SubpassMergeFeedbackTest(void)110 SubpassMergeFeedbackTest::~SubpassMergeFeedbackTest (void)
111 {
112 }
113 
createInstance(Context & context) const114 TestInstance* SubpassMergeFeedbackTest::createInstance (Context& context) const
115 {
116 	return new SubpassMergeFeedbackTestInstance(context, m_testParams);
117 }
118 
SubpassMergeFeedbackTestInstance(Context & context,const TestParams & testParams)119 SubpassMergeFeedbackTestInstance::SubpassMergeFeedbackTestInstance (Context&			context,
120 																	const TestParams&	testParams)
121 	: vkt::TestInstance	(context)
122 	, m_testParams      (testParams)
123 {
124 	// Check for renderpass2 extension
125 	context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
126 
127 	// Check for subpass merge feedback extension
128 	context.requireDeviceFunctionality("VK_EXT_subpass_merge_feedback");
129 }
130 
131 
~SubpassMergeFeedbackTestInstance(void)132 SubpassMergeFeedbackTestInstance::~SubpassMergeFeedbackTestInstance (void)
133 {
134 }
135 
createRenderPassAndVerify(const DeviceInterface & vk,VkDevice vkDevice)136 tcu::TestStatus SubpassMergeFeedbackTestInstance::createRenderPassAndVerify (const DeviceInterface&	vk,
137 																			 VkDevice				vkDevice)
138 {
139 	const VkImageAspectFlags	aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
140 
141 	std::vector<AttachmentDescription2> attachmentDescriptions;
142 	std::vector<AttachmentReference2> resultAttachments;
143 	std::vector<AttachmentReference2> inputAttachments;
144 	std::vector<VkRenderPassCreationControlEXT> subpassMergeControls;
145 	std::vector<VkRenderPassSubpassFeedbackCreateInfoEXT> subpassFeedbackCreateInfos;
146 	std::vector<VkRenderPassSubpassFeedbackInfoEXT> subpassFeedbackInfos;
147 	std::vector<SubpassDescription2> subpassDescriptions;
148 
149 	for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
150 	{
151 		attachmentDescriptions.emplace_back(
152 			nullptr,								// const void*						pNext
153 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
154 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
155 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
156 			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp
157 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
158 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
159 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
160 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
161 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
162 		);
163 
164 		resultAttachments.emplace_back(
165 			nullptr,								// const void*			pNext
166 			i,											// deUint32				attachment
167 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout		layout
168 			aspectMask									// VkImageAspectFlags	aspectMask
169 		);
170 
171 		inputAttachments.emplace_back(
172 			nullptr,								// const void*			pNext
173 			i,											// deUint32				attachment
174 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout		layout
175 			aspectMask									// VkImageAspectFlags	aspectMask
176 		);
177 
178 		VkBool32 disallowSubpassMerge = VK_FALSE;
179 		if (i == 1 && m_testParams.disallowMergeSubPass1)
180 		{
181 			disallowSubpassMerge = VK_TRUE;
182 		}
183 
184 		const VkRenderPassCreationControlEXT mergeControl = {
185 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT,			// VkStructureType			sType;
186 			nullptr,												// const void*				pNext;
187 			disallowSubpassMerge,									// VkBool32					disallowMerging;
188 		};
189 		subpassMergeControls.push_back( mergeControl );
190 
191 		VkRenderPassSubpassFeedbackInfoEXT feedbackInfo = {
192 			VK_SUBPASS_MERGE_STATUS_MERGED_EXT,							// VkSubpassMergeStatusEXT	subpassMergeStatus;
193 			"",															// description[VK_MAX_DESCRIPTION_SIZE];
194 			0															// uint32_t					postMergeIndex;
195 		};
196 		subpassFeedbackInfos.push_back( feedbackInfo );
197 	}
198 
199 	for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
200 	{
201 		const VkRenderPassSubpassFeedbackCreateInfoEXT feedbackCreateInfo = {
202 			VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT,	// VkStructureType			sType;
203 			&subpassMergeControls[i],									// const void*				pNext;
204 			&subpassFeedbackInfos[i]
205 		};
206 		subpassFeedbackCreateInfos.push_back( feedbackCreateInfo );
207 	}
208 
209 	for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
210 	{
211 		subpassDescriptions.emplace_back (
212 			&subpassFeedbackCreateInfos[i],
213 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
214 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
215 			0u,									// deUint32							viewMask
216 			(i>0) ? 1u : 0u,					// deUint32							inputAttachmentCount
217 			(i>0) ? &inputAttachments[i-1] : nullptr,						// const VkAttachmentReference*		pInputAttachments
218 			1u,									// deUint32							colorAttachmentCount
219 			&resultAttachments[i],				// const VkAttachmentReference*		pColorAttachments
220 			nullptr,						// const VkAttachmentReference*		pResolveAttachments
221 			nullptr,						// const VkAttachmentReference*		pDepthStencilAttachment
222 			0u,									// deUint32							preserveAttachmentCount
223 			nullptr						// const deUint32*					pPreserveAttachments
224 		);
225 	}
226 
227 	std::vector<SubpassDependency2> subpassDependencies;
228 	for (deUint32 i = 1; i < m_testParams.subpassCount; ++i)
229 	{
230 
231 		subpassDependencies.emplace_back(
232 			nullptr,										// const void*				pNext
233 			i-1,												// uint32_t					srcSubpass
234 			i,										// uint32_t					dstSubpass
235 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags		srcStageMask
236 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// VkPipelineStageFlags		dstStageMask
237 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask
238 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// VkAccessFlags			dstAccessMask
239 			VK_DEPENDENCY_BY_REGION_BIT,					// VkDependencyFlags		dependencyFlags
240 			0u												// deInt32					viewOffset
241 		);
242 	}
243 
244 
245 	VkBool32 disallowMerging = VK_FALSE;
246 	if (m_testParams.disallowMergeRenderpass)
247 	{
248 		disallowMerging = VK_TRUE;
249 	}
250 
251 	const VkRenderPassCreationControlEXT renderpassControl =
252 	{
253 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT,						// VkStructureType			sType;
254 			DE_NULL,																// const void*				pNext;
255 			disallowMerging															// VkBool32					disallowMerging;
256 	};
257 
258 	VkRenderPassCreationFeedbackInfoEXT renderpassFeedbackInfo =
259 	{
260 		0                     // uint32_t                                     postMergeSubpassCount;
261 	};
262 
263 	VkRenderPassCreationFeedbackCreateInfoEXT renderpassFeedbackCreateInfo =
264 	{
265 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT,				// VkStructureType			sType;
266 			&renderpassControl,														// const void*				pNext;
267 			&renderpassFeedbackInfo
268 	};
269 
270 	const RenderPassCreateInfo2	renderPassInfo					(
271 		&renderpassFeedbackCreateInfo,					// const void*						pNext
272 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
273 		static_cast<deUint32>(attachmentDescriptions.size()),					// deUint32							attachmentCount
274 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments
275 		static_cast<deUint32>(subpassDescriptions.size()),					// deUint32							subpassCount
276 		subpassDescriptions.data(),					// const VkSubpassDescription*		pSubpasses
277 		static_cast<deUint32>(subpassDependencies.size()),											// deUint32							dependencyCount
278 		subpassDependencies.data(),							// const VkSubpassDependency*		pDependencies
279 		0u,											// deUint32							correlatedViewMaskCount
280 		nullptr								// const deUint32*					pCorrelatedViewMasks
281 	);
282 
283 	Move<VkRenderPass> renderPass = renderPassInfo.createRenderPass(vk, vkDevice);
284 
285 	// Verify merge status flags
286 	if (m_testParams.disallowMergeRenderpass)
287 	{
288 		if (renderpassFeedbackInfo.postMergeSubpassCount != m_testParams.subpassCount)
289 		{
290 			return tcu::TestStatus::fail("Fail");
291 		}
292 
293 		for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
294 		{
295 			if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT)
296 			{
297 				return tcu::TestStatus::fail("Fail");
298 			}
299 
300 			if (i > 0 &&
301 				subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex == subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex)
302 			{
303 				return tcu::TestStatus::fail("Fail");
304 			}
305 		}
306 	}
307 	else
308 	{
309 		if (renderpassFeedbackInfo.postMergeSubpassCount > m_testParams.subpassCount)
310 		{
311 			return tcu::TestStatus::fail("Fail");
312 		}
313 
314 		if (m_testParams.subpassCount == 1 &&
315 			subpassFeedbackCreateInfos[0].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT)
316 		{
317 			return tcu::TestStatus::fail("Fail");
318 		}
319 
320 		for (deUint32 i = 1; i < m_testParams.subpassCount; ++i)
321 		{
322 			if (i == 1 && m_testParams.disallowMergeSubPass1 &&
323 				subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT)
324 			{
325 				return tcu::TestStatus::fail("Fail");
326 			}
327 
328 			if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus == VK_SUBPASS_MERGE_STATUS_MERGED_EXT &&
329 				subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex != subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex)
330 			{
331 				return tcu::TestStatus::fail("Fail");
332 			}
333 
334 			if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_MERGED_EXT &&
335 				subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex == subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex)
336 			{
337 				return tcu::TestStatus::fail("Fail");
338 			}
339 		}
340 	}
341 
342 	return tcu::TestStatus::pass("Pass");
343 }
344 
iterate(void)345 tcu::TestStatus SubpassMergeFeedbackTestInstance::iterate (void)
346 {
347 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
348 	const VkDevice				vkDevice	= m_context.getDevice();
349 
350 	// Create render pass
351 	return createRenderPassAndVerify(vk, vkDevice);
352 }
353 
354 } // anonymous
355 
createRenderPassSubpassMergeFeedbackTests(tcu::TestContext & testCtx,const RenderingType renderingType)356 tcu::TestCaseGroup* createRenderPassSubpassMergeFeedbackTests (tcu::TestContext& testCtx, const RenderingType renderingType)
357 {
358 	if (renderingType != RENDERING_TYPE_RENDERPASS2)
359 	{
360 		return nullptr;
361 	}
362 
363 	de::MovePtr<tcu::TestCaseGroup>		subpassMergeFeedbackTests		(new tcu::TestCaseGroup(testCtx, "subpass_merge_feedback", "Subpass merge feedback tests"));
364 
365 	{
366 		TestParams			params;
367 		const std::string	testName = std::string("single_subpass");
368 
369 		params.subpassCount = 1;
370 		params.disallowMergeRenderpass = false;
371 		params.disallowMergeSubPass1 = false;
372 
373 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params));
374 	}
375 	{
376 		TestParams			params;
377 		const std::string	testName = std::string("single_subpass_disallow_renderpass_merge");
378 
379 		params.subpassCount = 1;
380 		params.disallowMergeRenderpass = true;
381 		params.disallowMergeSubPass1 = false;
382 
383 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params));
384 	}
385 	{
386 		TestParams			params;
387 		const std::string	testName = std::string("three_subpasses");
388 
389 		params.subpassCount = 3;
390 		params.disallowMergeRenderpass = false;
391 		params.disallowMergeSubPass1 = false;
392 
393 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params));
394 	}
395 	{
396 		TestParams			params;
397 		const std::string	testName = std::string("three_subpasses_disallow_renderpass_merge");
398 
399 		params.subpassCount = 3;
400 		params.disallowMergeRenderpass = true;
401 		params.disallowMergeSubPass1 = false;
402 
403 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params));
404 	}
405 	{
406 		TestParams			params;
407 		const std::string	testName = std::string("three_subpasses_disallow_subpass_merge");
408 
409 		params.subpassCount = 3;
410 		params.disallowMergeRenderpass = false;
411 		params.disallowMergeSubPass1 = true;
412 
413 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params));
414 	}
415 	{
416 		TestParams			params;
417 		const std::string	testName = std::string("many_subpasses");
418 
419 		params.subpassCount = 32;
420 		params.disallowMergeRenderpass = false;
421 		params.disallowMergeSubPass1 = false;
422 
423 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params));
424 	}
425 
426 	return subpassMergeFeedbackTests.release();
427 }
428 
429 } // renderpass
430 } // vkt
431