• 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 TestParams&	testParams);
79 	virtual								~SubpassMergeFeedbackTest	(void);
80 	virtual TestInstance*				createInstance			(Context&			context) const;
81 private:
82 	const TestParams					m_testParams;
83 };
84 
85 class SubpassMergeFeedbackTestInstance : public vkt::TestInstance
86 {
87 public:
88 										SubpassMergeFeedbackTestInstance	(Context&				context,
89 																		     const TestParams&		testParams);
90 	virtual								~SubpassMergeFeedbackTestInstance	(void);
91 	virtual tcu::TestStatus				iterate							    (void);
92 private:
93 
94 	tcu::TestStatus                     createRenderPassAndVerify           (const DeviceInterface&	vk,
95 																			 VkDevice				vkDevice);
96 
97 	const TestParams					m_testParams;
98 };
99 
SubpassMergeFeedbackTest(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)100 SubpassMergeFeedbackTest::SubpassMergeFeedbackTest (tcu::TestContext&	testContext,
101 											const std::string&	name,
102 											const TestParams&	testParams)
103 	: vkt::TestCase	(testContext, name)
104 	, m_testParams	(testParams)
105 {
106 }
107 
~SubpassMergeFeedbackTest(void)108 SubpassMergeFeedbackTest::~SubpassMergeFeedbackTest (void)
109 {
110 }
111 
createInstance(Context & context) const112 TestInstance* SubpassMergeFeedbackTest::createInstance (Context& context) const
113 {
114 	return new SubpassMergeFeedbackTestInstance(context, m_testParams);
115 }
116 
SubpassMergeFeedbackTestInstance(Context & context,const TestParams & testParams)117 SubpassMergeFeedbackTestInstance::SubpassMergeFeedbackTestInstance (Context&			context,
118 																	const TestParams&	testParams)
119 	: vkt::TestInstance	(context)
120 	, m_testParams      (testParams)
121 {
122 	// Check for renderpass2 extension
123 	context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
124 
125 	// Check for subpass merge feedback extension
126 	context.requireDeviceFunctionality("VK_EXT_subpass_merge_feedback");
127 }
128 
129 
~SubpassMergeFeedbackTestInstance(void)130 SubpassMergeFeedbackTestInstance::~SubpassMergeFeedbackTestInstance (void)
131 {
132 }
133 
createRenderPassAndVerify(const DeviceInterface & vk,VkDevice vkDevice)134 tcu::TestStatus SubpassMergeFeedbackTestInstance::createRenderPassAndVerify (const DeviceInterface&	vk,
135 																			 VkDevice				vkDevice)
136 {
137 	const VkImageAspectFlags	aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
138 
139 	std::vector<AttachmentDescription2> attachmentDescriptions;
140 	std::vector<AttachmentReference2> resultAttachments;
141 	std::vector<AttachmentReference2> inputAttachments;
142 	std::vector<VkRenderPassCreationControlEXT> subpassMergeControls;
143 	std::vector<VkRenderPassSubpassFeedbackCreateInfoEXT> subpassFeedbackCreateInfos;
144 	std::vector<VkRenderPassSubpassFeedbackInfoEXT> subpassFeedbackInfos;
145 	std::vector<SubpassDescription2> subpassDescriptions;
146 
147 	for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
148 	{
149 		attachmentDescriptions.emplace_back(
150 			nullptr,								// const void*						pNext
151 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
152 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
153 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
154 			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp
155 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
156 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
157 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
158 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
159 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
160 		);
161 
162 		resultAttachments.emplace_back(
163 			nullptr,								// const void*			pNext
164 			i,											// deUint32				attachment
165 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout		layout
166 			aspectMask									// VkImageAspectFlags	aspectMask
167 		);
168 
169 		inputAttachments.emplace_back(
170 			nullptr,								// const void*			pNext
171 			i,											// deUint32				attachment
172 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout		layout
173 			aspectMask									// VkImageAspectFlags	aspectMask
174 		);
175 
176 		VkBool32 disallowSubpassMerge = VK_FALSE;
177 		if (i == 1 && m_testParams.disallowMergeSubPass1)
178 		{
179 			disallowSubpassMerge = VK_TRUE;
180 		}
181 
182 		const VkRenderPassCreationControlEXT mergeControl = {
183 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT,			// VkStructureType			sType;
184 			nullptr,												// const void*				pNext;
185 			disallowSubpassMerge,									// VkBool32					disallowMerging;
186 		};
187 		subpassMergeControls.push_back( mergeControl );
188 
189 		VkRenderPassSubpassFeedbackInfoEXT feedbackInfo = {
190 			VK_SUBPASS_MERGE_STATUS_MERGED_EXT,							// VkSubpassMergeStatusEXT	subpassMergeStatus;
191 			"",															// description[VK_MAX_DESCRIPTION_SIZE];
192 			0															// uint32_t					postMergeIndex;
193 		};
194 		subpassFeedbackInfos.push_back( feedbackInfo );
195 	}
196 
197 	for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
198 	{
199 		const VkRenderPassSubpassFeedbackCreateInfoEXT feedbackCreateInfo = {
200 			VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT,	// VkStructureType			sType;
201 			&subpassMergeControls[i],									// const void*				pNext;
202 			&subpassFeedbackInfos[i]
203 		};
204 		subpassFeedbackCreateInfos.push_back( feedbackCreateInfo );
205 	}
206 
207 	for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
208 	{
209 		subpassDescriptions.emplace_back (
210 			&subpassFeedbackCreateInfos[i],
211 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
212 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
213 			0u,									// deUint32							viewMask
214 			(i>0) ? 1u : 0u,					// deUint32							inputAttachmentCount
215 			(i>0) ? &inputAttachments[i-1] : nullptr,						// const VkAttachmentReference*		pInputAttachments
216 			1u,									// deUint32							colorAttachmentCount
217 			&resultAttachments[i],				// const VkAttachmentReference*		pColorAttachments
218 			nullptr,						// const VkAttachmentReference*		pResolveAttachments
219 			nullptr,						// const VkAttachmentReference*		pDepthStencilAttachment
220 			0u,									// deUint32							preserveAttachmentCount
221 			nullptr						// const deUint32*					pPreserveAttachments
222 		);
223 	}
224 
225 	std::vector<SubpassDependency2> subpassDependencies;
226 	for (deUint32 i = 1; i < m_testParams.subpassCount; ++i)
227 	{
228 
229 		subpassDependencies.emplace_back(
230 			nullptr,										// const void*				pNext
231 			i-1,												// uint32_t					srcSubpass
232 			i,										// uint32_t					dstSubpass
233 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags		srcStageMask
234 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// VkPipelineStageFlags		dstStageMask
235 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask
236 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// VkAccessFlags			dstAccessMask
237 			VK_DEPENDENCY_BY_REGION_BIT,					// VkDependencyFlags		dependencyFlags
238 			0u												// deInt32					viewOffset
239 		);
240 	}
241 
242 
243 	VkBool32 disallowMerging = VK_FALSE;
244 	if (m_testParams.disallowMergeRenderpass)
245 	{
246 		disallowMerging = VK_TRUE;
247 	}
248 
249 	const VkRenderPassCreationControlEXT renderpassControl =
250 	{
251 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT,						// VkStructureType			sType;
252 			DE_NULL,																// const void*				pNext;
253 			disallowMerging															// VkBool32					disallowMerging;
254 	};
255 
256 	VkRenderPassCreationFeedbackInfoEXT renderpassFeedbackInfo =
257 	{
258 		0                     // uint32_t                                     postMergeSubpassCount;
259 	};
260 
261 	VkRenderPassCreationFeedbackCreateInfoEXT renderpassFeedbackCreateInfo =
262 	{
263 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT,				// VkStructureType			sType;
264 			&renderpassControl,														// const void*				pNext;
265 			&renderpassFeedbackInfo
266 	};
267 
268 	const RenderPassCreateInfo2	renderPassInfo					(
269 		&renderpassFeedbackCreateInfo,					// const void*						pNext
270 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
271 		static_cast<deUint32>(attachmentDescriptions.size()),					// deUint32							attachmentCount
272 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments
273 		static_cast<deUint32>(subpassDescriptions.size()),					// deUint32							subpassCount
274 		subpassDescriptions.data(),					// const VkSubpassDescription*		pSubpasses
275 		static_cast<deUint32>(subpassDependencies.size()),											// deUint32							dependencyCount
276 		subpassDependencies.data(),							// const VkSubpassDependency*		pDependencies
277 		0u,											// deUint32							correlatedViewMaskCount
278 		nullptr								// const deUint32*					pCorrelatedViewMasks
279 	);
280 
281 	Move<VkRenderPass> renderPass = renderPassInfo.createRenderPass(vk, vkDevice);
282 
283 	// Verify merge status flags
284 	if (m_testParams.disallowMergeRenderpass)
285 	{
286 		if (renderpassFeedbackInfo.postMergeSubpassCount != m_testParams.subpassCount)
287 		{
288 			return tcu::TestStatus::fail("Fail");
289 		}
290 
291 		for (deUint32 i = 0; i < m_testParams.subpassCount; ++i)
292 		{
293 			if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT)
294 			{
295 				return tcu::TestStatus::fail("Fail");
296 			}
297 
298 			if (i > 0 &&
299 				subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex == subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex)
300 			{
301 				return tcu::TestStatus::fail("Fail");
302 			}
303 		}
304 	}
305 	else
306 	{
307 		if (renderpassFeedbackInfo.postMergeSubpassCount > m_testParams.subpassCount)
308 		{
309 			return tcu::TestStatus::fail("Fail");
310 		}
311 
312 		if (m_testParams.subpassCount == 1 &&
313 			subpassFeedbackCreateInfos[0].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT)
314 		{
315 			return tcu::TestStatus::fail("Fail");
316 		}
317 
318 		for (deUint32 i = 1; i < m_testParams.subpassCount; ++i)
319 		{
320 			if (i == 1 && m_testParams.disallowMergeSubPass1 &&
321 				subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT)
322 			{
323 				return tcu::TestStatus::fail("Fail");
324 			}
325 
326 			if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus == VK_SUBPASS_MERGE_STATUS_MERGED_EXT &&
327 				subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex != subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex)
328 			{
329 				return tcu::TestStatus::fail("Fail");
330 			}
331 
332 			if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_MERGED_EXT &&
333 				subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex == subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex)
334 			{
335 				return tcu::TestStatus::fail("Fail");
336 			}
337 		}
338 	}
339 
340 	return tcu::TestStatus::pass("Pass");
341 }
342 
iterate(void)343 tcu::TestStatus SubpassMergeFeedbackTestInstance::iterate (void)
344 {
345 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
346 	const VkDevice				vkDevice	= m_context.getDevice();
347 
348 	// Create render pass
349 	return createRenderPassAndVerify(vk, vkDevice);
350 }
351 
352 } // anonymous
353 
createRenderPassSubpassMergeFeedbackTests(tcu::TestContext & testCtx,const RenderingType renderingType)354 tcu::TestCaseGroup* createRenderPassSubpassMergeFeedbackTests (tcu::TestContext& testCtx, const RenderingType renderingType)
355 {
356 	if (renderingType != RENDERING_TYPE_RENDERPASS2)
357 	{
358 		return nullptr;
359 	}
360 
361 	de::MovePtr<tcu::TestCaseGroup>		subpassMergeFeedbackTests		(new tcu::TestCaseGroup(testCtx, "subpass_merge_feedback"));
362 
363 	{
364 		TestParams			params;
365 		const std::string	testName = std::string("single_subpass");
366 
367 		params.subpassCount = 1;
368 		params.disallowMergeRenderpass = false;
369 		params.disallowMergeSubPass1 = false;
370 
371 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, params));
372 	}
373 	{
374 		TestParams			params;
375 		const std::string	testName = std::string("single_subpass_disallow_renderpass_merge");
376 
377 		params.subpassCount = 1;
378 		params.disallowMergeRenderpass = true;
379 		params.disallowMergeSubPass1 = false;
380 
381 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, params));
382 	}
383 	{
384 		TestParams			params;
385 		const std::string	testName = std::string("three_subpasses");
386 
387 		params.subpassCount = 3;
388 		params.disallowMergeRenderpass = false;
389 		params.disallowMergeSubPass1 = false;
390 
391 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, params));
392 	}
393 	{
394 		TestParams			params;
395 		const std::string	testName = std::string("three_subpasses_disallow_renderpass_merge");
396 
397 		params.subpassCount = 3;
398 		params.disallowMergeRenderpass = true;
399 		params.disallowMergeSubPass1 = false;
400 
401 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, params));
402 	}
403 	{
404 		TestParams			params;
405 		const std::string	testName = std::string("three_subpasses_disallow_subpass_merge");
406 
407 		params.subpassCount = 3;
408 		params.disallowMergeRenderpass = false;
409 		params.disallowMergeSubPass1 = true;
410 
411 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, params));
412 	}
413 	{
414 		TestParams			params;
415 		const std::string	testName = std::string("many_subpasses");
416 
417 		params.subpassCount = 32;
418 		params.disallowMergeRenderpass = false;
419 		params.disallowMergeSubPass1 = false;
420 
421 		subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, params));
422 	}
423 
424 	return subpassMergeFeedbackTests.release();
425 }
426 
427 } // renderpass
428 } // vkt
429