• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Google 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 Early pipeline destroying tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineEarlyDestroyTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deUniquePtr.hpp"
34 #include "tcuTexture.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkImageWithMemory.hpp"
37 #include "vkBufferWithMemory.hpp"
38 #include "vkCmdUtil.hpp"
39 
40 namespace vkt
41 {
42 namespace pipeline
43 {
44 
45 using namespace vk;
46 
47 namespace
48 {
49 
50 struct TestParams
51 {
52 	PipelineConstructionType	pipelineConstructionType;
53 	bool						usePipelineCache;
54 };
55 
checkSupport(Context & context,TestParams testParams)56 void checkSupport(Context& context, TestParams testParams)
57 {
58 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), testParams.pipelineConstructionType);
59 }
60 
initPrograms(SourceCollections & programCollection,TestParams testParams)61 void initPrograms (SourceCollections& programCollection, TestParams testParams)
62 {
63 	DE_UNREF(testParams.usePipelineCache);
64 
65 	programCollection.glslSources.add("color_vert") << glu::VertexSource(
66 		"#version 450\n"
67 		"vec2 vertices[3];\n"
68 		"\n"
69 		"void main()\n"
70 		"{\n"
71 		"   vertices[0] = vec2(-1.0, -1.0);\n"
72 		"   vertices[1] = vec2( 1.0, -1.0);\n"
73 		"   vertices[2] = vec2( 0.0,  1.0);\n"
74 		"   gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n"
75 		"}\n");
76 
77 	programCollection.glslSources.add("color_frag") << glu::FragmentSource(
78 		"#version 450\n"
79 		"\n"
80 		"layout(location = 0) out vec4 uFragColor;\n"
81 		"\n"
82 		"void main()\n"
83 		"{\n"
84 		"   uFragColor = vec4(0,1,0,1);\n"
85 		"}\n");
86 }
87 
testEarlyDestroy(Context & context,const TestParams & params,bool destroyLayout)88 tcu::TestStatus testEarlyDestroy (Context& context, const TestParams& params, bool destroyLayout)
89 {
90 	const DeviceInterface&								vk								= context.getDeviceInterface();
91 	const VkDevice										vkDevice						= context.getDevice();
92 	const Unique<VkShaderModule>						vertexShaderModule				(createShaderModule(vk, vkDevice, context.getBinaryCollection().get("color_vert"), 0));
93 	const Unique<VkShaderModule>						fragmentShaderModule			(createShaderModule(vk, vkDevice, context.getBinaryCollection().get("color_frag"), 0));
94 
95 	const Unique<VkCommandPool>							cmdPool							(createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
96 	const Unique<VkCommandBuffer>						cmdBuffer						(allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
97 
98 	const VkPipelineLayoutCreateInfo					pipelineLayoutCreateInfo		=
99 	{
100 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,									// VkStructureType					sType;
101 		DE_NULL,																		// const void*						pNext;
102 		0u,																				// VkPipelineLayoutCreateFlags		flags;
103 		0u,																				// deUint32							setLayoutCount;
104 		DE_NULL,																		// const VkDescriptorSetLayout*		pSetLayouts;
105 		0u,																				// deUint32							pushConstantRangeCount;
106 		DE_NULL																			// const VkPushConstantRange*		pPushConstantRanges;
107 	};
108 
109 	// Multiple passes for destroy layout in order to increase the chance of crashing if some resource/state gets carried over from previous iterations.
110 	int numTests = destroyLayout ? 3 : 1;
111 	for(int i = 0; i < numTests; ++i)
112 	{
113 		Move<VkPipelineLayout>							pipelineLayout					(createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo, DE_NULL));
114 		const Unique<VkRenderPass>						renderPass						(makeRenderPass(vk, vkDevice, VK_FORMAT_R8G8B8A8_UNORM));
115 		const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
116 		{
117 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,					// VkStructureType							sType;
118 			DE_NULL,																	// const void*								pNext;
119 			0u,																			// VkPipelineVertexInputStateCreateFlags	flags;
120 			0u,																			// deUint32									vertexBindingDescriptionCount;
121 			DE_NULL,																	// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
122 			0u,																			// deUint32									vertexAttributeDescriptionCount;
123 			DE_NULL																		// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
124 		};
125 		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateCreateInfo	=
126 		{
127 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,				// VkStructureType							sType;
128 			DE_NULL,																	// const void*								pNext;
129 			0u,																			// VkPipelineInputAssemblyStateCreateFlags	flags;
130 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,										// VkPrimitiveTopology						topology;
131 			VK_FALSE																	// VkBool32									primitiveRestartEnable;
132 		};
133 		const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
134 		{
135 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,					// VkStructureType							sType;
136 			DE_NULL,																	// const void*								pNext;
137 			0u,																			// VkPipelineRasterizationStateCreateFlags	flags;
138 			VK_FALSE,																	// VkBool32									depthClampEnable;
139 			VK_TRUE,																	// VkBool32									rasterizerDiscardEnable;
140 			VK_POLYGON_MODE_FILL,														// VkPolygonMode							polygonMode;
141 			VK_CULL_MODE_BACK_BIT,														// VkCullModeFlags							cullMode;
142 			VK_FRONT_FACE_CLOCKWISE,													// VkFrontFace								frontFace;
143 			VK_FALSE,																	// VkBool32									depthBiasEnable;
144 			0.0f,																		// float									depthBiasConstantFactor;
145 			0.0f,																		// float									depthBiasClamp;
146 			0.0f,																		// float									depthBiasSlopeFactor;
147 			1.0f																		// float									lineWidth;
148 		};
149 		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState		=
150 		{
151 			VK_FALSE,																	// VkBool32					blendEnable;
152 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor			srcColorBlendFactor;
153 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor			dstColorBlendFactor;
154 			VK_BLEND_OP_ADD,															// VkBlendOp				colorBlendOp;
155 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor			srcAlphaBlendFactor;
156 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor			dstAlphaBlendFactor;
157 			VK_BLEND_OP_ADD,															// VkBlendOp				alphaBlendOp;
158 			0xf																			// VkColorComponentFlags	colorWriteMask;
159 		};
160 		const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo		=
161 		{
162 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,					// VkStructureType								sType;
163 			DE_NULL,																	// const void*									pNext;
164 			0u,																			// VkPipelineColorBlendStateCreateFlags			flags;
165 			VK_FALSE,																	// VkBool32										logicOpEnable;
166 			VK_LOGIC_OP_CLEAR,															// VkLogicOp									logicOp;
167 			1u,																			// deUint32										attachmentCount;
168 			&colorBlendAttachmentState,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
169 			{ 0.0f, 0.0f, 0.0f, 0.0f }													// float										blendConstants[4];
170 		};
171 		const VkPipelineCacheCreateInfo					pipelineCacheCreateInfo			=
172 		{
173 			VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,								// VkStructureType				sType;
174 			DE_NULL,																	// const void*					pNext;
175 #ifndef CTS_USES_VULKANSC
176 			(VkPipelineCacheCreateFlags)0u,												// VkPipelineCacheCreateFlags	flags;
177 			0u,																			// size_t						initialDataSize;
178 			DE_NULL																		// const void*					pInitialData;
179 #else
180 			VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
181 				VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,					// VkPipelineCacheCreateFlags	flags;
182 			context.getResourceInterface()->getCacheDataSize(),							// deUintptr					initialDataSize;
183 			context.getResourceInterface()->getCacheData()								// const void*					pInitialData;
184 #endif // CTS_USES_VULKANSC
185 		};
186 		const Unique<VkPipelineCache>					pipelineCache					(createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
187 
188 		const std::vector<VkViewport>					viewports						{};
189 		const std::vector<VkRect2D>						scissors						{};
190 		GraphicsPipelineWrapper							graphicsPipeline				(vk, vkDevice, params.pipelineConstructionType, VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT);
191 
192 		graphicsPipeline.disableViewportState()
193 						.setDefaultMultisampleState()
194 						.setDefaultDepthStencilState()
195 						.setupVertexInputState(&vertexInputStateCreateInfo, &inputAssemblyStateCreateInfo)
196 						.setupPreRasterizationShaderState(viewports,
197 														  scissors,
198 														  *pipelineLayout,
199 														  *renderPass,
200 														  0u,
201 														  *vertexShaderModule,
202 														  &rasterizationStateCreateInfo)
203 						.setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, *fragmentShaderModule)
204 						.setupFragmentOutputState(*renderPass, 0u, &colorBlendStateCreateInfo)
205 						.setMonolithicPipelineLayout(*pipelineLayout)
206 						.buildPipeline(params.usePipelineCache ? *pipelineCache : DE_NULL);
207 
208 		const deUint32 framebufferWidth													= 32;
209 		const deUint32 framebufferHeight												= 32;
210 		if (destroyLayout)
211 		{
212 			// This will destroy the pipelineLayout when going out of enclosing scope
213 			Move<VkPipelineLayout> layout(pipelineLayout);
214 		}
215 		const VkCommandBufferBeginInfo					cmdBufferBeginInfo				=
216 		{
217 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,								// VkStructureType							sType;
218 			DE_NULL,																	// const void*								pNext;
219 			0u,																			// VkCommandBufferUsageFlags				flags;
220 			(const VkCommandBufferInheritanceInfo*)DE_NULL								// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
221 		};
222 		if (!destroyLayout) {
223 			VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
224 			VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
225 		} else {
226 			auto&										allocator						= context.getDefaultAllocator();
227 			const auto									queue							= context.getUniversalQueue();
228 			const VkFormat								attachmentFormat				= VK_FORMAT_R8G8B8A8_UNORM;
229 			const tcu::TextureFormat					textureFormat					= mapVkFormat(attachmentFormat);
230 			const VkDeviceSize							imageSize						= framebufferWidth * framebufferHeight * textureFormat.getPixelSize();
231 			const VkImageCreateInfo						imageCreateInfo					=
232 			{
233 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
234 				DE_NULL,																// const void*				pNext;
235 				(VkImageCreateFlags)0,													// VkImageCreateFlags		flags;
236 				VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
237 				attachmentFormat,														// VkFormat					format;
238 				{ framebufferWidth, framebufferHeight, 1u },							// VkExtent3D				extent;
239 				1u,																		// deUint32					mipLevels;
240 				1u,																		// deUint32					arrayLayers;
241 				VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
242 				VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
243 				VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
244 				VK_IMAGE_USAGE_TRANSFER_DST_BIT |
245 				VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,									// VkImageUsageFlags		usage;
246 				VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
247 				0u,																		// deUint32					queueFamilyIndexCount;
248 				DE_NULL,																// const deUint32*			pQueueFamilyIndices;
249 				VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
250 			};
251 			const ImageWithMemory						attachmentImage					(vk, vkDevice, context.getDefaultAllocator(), imageCreateInfo, MemoryRequirement::Any);
252 			const VkImageSubresourceRange				colorSubresourceRange			= { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u };
253 			const Unique<VkImageView>					attachmentImageView				(vk::makeImageView(vk, vkDevice, *attachmentImage, VK_IMAGE_VIEW_TYPE_2D, attachmentFormat, colorSubresourceRange));
254 			const VkBufferCreateInfo					imageBufferCreateInfo			= vk::makeBufferCreateInfo(imageSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
255 			const BufferWithMemory						imageBuffer						(vk, vkDevice, allocator, imageBufferCreateInfo, vk::MemoryRequirement::HostVisible);
256 			const Unique<VkFramebuffer>					framebuffer						(vk::makeFramebuffer(vk, vkDevice, *renderPass, *attachmentImageView, framebufferWidth, framebufferHeight, 1u));
257 
258 			VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
259 			const tcu::Vec4								clearColor						= { 0.2f, 0.6f, 0.8f, 1.0f };
260 			VkClearValue								clearValue						=
261 			{
262 				{ { clearColor.x(), clearColor.y(),
263 					clearColor.z(), clearColor.w() } }									// float						float32[4];
264 			};
265 			VkClearAttachment								attachment						=
266 			{
267 				VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags			aspectMask;
268 				0u,																		// deUint32						colorAttachment;
269 				clearValue																// VkClearValue					clearValue;
270 			};
271 			const VkRect2D								renderArea						= { { 0, 0 }, { framebufferWidth, framebufferHeight } };
272 			const VkClearRect								rect							=
273 			{
274 				renderArea,																// VkRect2D						rect
275 				0u,																		// uint32_t						baseArrayLayer
276 				1u																		// uint32_t						layerCount
277 			};
278 			const VkRenderPassBeginInfo					renderPassBeginInfo				=
279 			{
280 				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,								// VkStructureType				sType;
281 				DE_NULL,																// const void*					pNext;
282 				*renderPass,															// VkRenderPass					renderPass;
283 				*framebuffer,															// VkFramebuffer				framebuffer;
284 				renderArea,																// VkRect2D						renderArea;
285 				1u,																		// deUint32						clearValueCount;
286 				&clearValue																// const VkClearValue*			pClearValues;
287 			};
288 			vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
289 			vk.cmdClearAttachments(*cmdBuffer, 1, &attachment, 1, &rect);
290 			vk.cmdEndRenderPass(*cmdBuffer);
291 			vk::copyImageToBuffer(vk, *cmdBuffer, *attachmentImage, *imageBuffer, tcu::IVec2(framebufferWidth, framebufferHeight));
292 			VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
293 
294 			vk::submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
295 			VK_CHECK(vk.resetCommandBuffer(*cmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT));
296 			const auto&									imageBufferAlloc				= imageBuffer.getAllocation();
297 			vk::invalidateAlloc(vk, vkDevice, imageBufferAlloc);
298 
299 			const auto									imageBufferPtr					= reinterpret_cast<const char*>(imageBufferAlloc.getHostPtr()) + imageBufferAlloc.getOffset();
300 			const tcu::ConstPixelBufferAccess			imagePixels						(textureFormat, framebufferWidth, framebufferHeight, 1u, imageBufferPtr);
301 
302 #ifdef CTS_USES_VULKANSC
303 			if (context.getTestContext().getCommandLine().isSubProcess())
304 #endif // CTS_USES_VULKANSC
305 			{
306 				for (int z = 0; z < imagePixels.getDepth(); ++z)
307 				for (int y = 0; y < imagePixels.getHeight(); ++y)
308 				for (int x = 0; x < imagePixels.getWidth(); ++x)
309 				{
310 					const auto pixel = imagePixels.getPixel(x, y, z);
311 					if (pixel != clearColor) {
312 										std::ostringstream msg; msg << "Pixel value mismatch after framebuffer clear." << " diff: " << pixel << " vs " << clearColor;
313 
314 						return tcu::TestStatus::fail(msg.str()/*"Pixel value mismatch after framebuffer clear."*/);
315 					}
316 				}
317 			}
318 		}
319 	}
320 	// Passes as long as no crash occurred.
321 	return tcu::TestStatus::pass("Pass");
322 }
323 
testEarlyDestroyKeepLayout(Context & context,TestParams params)324 tcu::TestStatus testEarlyDestroyKeepLayout (Context& context, TestParams params)
325 {
326 	return testEarlyDestroy (context, params, false);
327 }
328 
testEarlyDestroyDestroyLayout(Context & context,TestParams params)329 tcu::TestStatus testEarlyDestroyDestroyLayout (Context& context, TestParams params)
330 {
331 	return testEarlyDestroy (context, params, true);
332 }
333 
addEarlyDestroyTestCasesWithFunctions(tcu::TestCaseGroup * group,PipelineConstructionType pipelineConstructionType)334 void addEarlyDestroyTestCasesWithFunctions (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
335 {
336 	TestParams params
337 	{
338 		pipelineConstructionType,
339 		true
340 	};
341 
342 	addFunctionCaseWithPrograms(group, "cache", "", checkSupport, initPrograms, testEarlyDestroyKeepLayout, params);
343 	params.usePipelineCache = false;
344 	addFunctionCaseWithPrograms(group, "no_cache", "", checkSupport, initPrograms, testEarlyDestroyKeepLayout, params);
345 	params.usePipelineCache = true;
346 	addFunctionCaseWithPrograms(group, "cache_destroy_layout", "", checkSupport, initPrograms, testEarlyDestroyDestroyLayout, params);
347 	params.usePipelineCache = false;
348 	addFunctionCaseWithPrograms(group, "no_cache_destroy_layout", "", checkSupport, initPrograms, testEarlyDestroyDestroyLayout, params);
349 }
350 
351 } // anonymous
352 
createEarlyDestroyTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)353 tcu::TestCaseGroup* createEarlyDestroyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
354 {
355 	return createTestGroup(testCtx, "early_destroy", "Tests where pipeline is destroyed early", addEarlyDestroyTestCasesWithFunctions, pipelineConstructionType);
356 }
357 
358 } // pipeline
359 } // vkt
360