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