1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 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 Synchronization tests utilities
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSynchronizationUtil.hpp"
25 #include "vkTypeUtil.hpp"
26 #include "vkCmdUtil.hpp"
27 #include "deStringUtil.hpp"
28 
29 namespace vkt
30 {
31 namespace synchronization
32 {
33 using namespace vk;
34 
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)35 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
36 										 const VkBufferUsageFlags	usage)
37 {
38 	const VkBufferCreateInfo bufferCreateInfo =
39 	{
40 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
41 		DE_NULL,								// const void*			pNext;
42 		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
43 		bufferSize,								// VkDeviceSize			size;
44 		usage,									// VkBufferUsageFlags	usage;
45 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
46 		0u,										// deUint32				queueFamilyIndexCount;
47 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
48 	};
49 	return bufferCreateInfo;
50 }
51 
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)52 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
53 {
54 	const VkCommandBufferAllocateInfo info =
55 	{
56 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
57 		DE_NULL,											// const void*			pNext;
58 		commandPool,										// VkCommandPool		commandPool;
59 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
60 		1u,													// deUint32				commandBufferCount;
61 	};
62 	return allocateCommandBuffer(vk, device, &info);
63 }
64 
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)65 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
66 										 const VkDevice					device,
67 										 const VkDescriptorPool			descriptorPool,
68 										 const VkDescriptorSetLayout	setLayout)
69 {
70 	const VkDescriptorSetAllocateInfo info =
71 	{
72 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
73 		DE_NULL,											// const void*					pNext;
74 		descriptorPool,										// VkDescriptorPool				descriptorPool;
75 		1u,													// deUint32						descriptorSetCount;
76 		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
77 	};
78 	return allocateDescriptorSet(vk, device, &info);
79 }
80 
makePipelineLayout(const DeviceInterface & vk,const VkDevice device,const VkDescriptorSetLayout descriptorSetLayout)81 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
82 										   const VkDevice				device,
83 										   const VkDescriptorSetLayout	descriptorSetLayout)
84 {
85 	const VkPipelineLayoutCreateInfo info =
86 	{
87 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
88 		DE_NULL,											// const void*					pNext;
89 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
90 		1u,													// deUint32						setLayoutCount;
91 		&descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
92 		0u,													// deUint32						pushConstantRangeCount;
93 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
94 	};
95 	return createPipelineLayout(vk, device, &info);
96 }
97 
makePipelineLayoutWithoutDescriptors(const DeviceInterface & vk,const VkDevice device)98 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&		vk,
99 															 const VkDevice				device)
100 {
101 	const VkPipelineLayoutCreateInfo info =
102 	{
103 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
104 		DE_NULL,											// const void*					pNext;
105 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
106 		0u,													// deUint32						setLayoutCount;
107 		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
108 		0u,													// deUint32						pushConstantRangeCount;
109 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
110 	};
111 	return createPipelineLayout(vk, device, &info);
112 }
113 
makeComputePipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkShaderModule shaderModule,const VkSpecializationInfo * specInfo,PipelineCacheData & pipelineCacheData)114 Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
115 									  const VkDevice				device,
116 									  const VkPipelineLayout		pipelineLayout,
117 									  const VkShaderModule			shaderModule,
118 									  const VkSpecializationInfo*	specInfo,
119 									  PipelineCacheData&			pipelineCacheData)
120 {
121 	const VkPipelineShaderStageCreateInfo shaderStageInfo =
122 	{
123 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
124 		DE_NULL,												// const void*						pNext;
125 		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags	flags;
126 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
127 		shaderModule,											// VkShaderModule					module;
128 		"main",													// const char*						pName;
129 		specInfo,												// const VkSpecializationInfo*		pSpecializationInfo;
130 	};
131 	const VkComputePipelineCreateInfo pipelineInfo =
132 	{
133 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
134 		DE_NULL,											// const void*						pNext;
135 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags			flags;
136 		shaderStageInfo,									// VkPipelineShaderStageCreateInfo	stage;
137 		pipelineLayout,										// VkPipelineLayout					layout;
138 		DE_NULL,											// VkPipeline						basePipelineHandle;
139 		0,													// deInt32							basePipelineIndex;
140 	};
141 
142 	{
143 		const vk::Unique<vk::VkPipelineCache>	pipelineCache	(pipelineCacheData.createPipelineCache(vk, device));
144 		vk::Move<vk::VkPipeline>				pipeline		(createComputePipeline(vk, device, *pipelineCache, &pipelineInfo));
145 
146 		// Refresh data from cache
147 		pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
148 
149 		return pipeline;
150 	}
151 }
152 
makeImageCreateInfo(const VkImageType imageType,const VkExtent3D & extent,const VkFormat format,const VkImageUsageFlags usage)153 VkImageCreateInfo makeImageCreateInfo (const VkImageType imageType, const VkExtent3D& extent, const VkFormat format, const VkImageUsageFlags usage)
154 {
155 	const VkImageCreateInfo imageInfo =
156 	{
157 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
158 		DE_NULL,									// const void*              pNext;
159 		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
160 		imageType,									// VkImageType              imageType;
161 		format,										// VkFormat                 format;
162 		extent,										// VkExtent3D               extent;
163 		1u,											// uint32_t                 mipLevels;
164 		1u,											// uint32_t                 arrayLayers;
165 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
166 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
167 		usage,										// VkImageUsageFlags        usage;
168 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
169 		0u,											// uint32_t                 queueFamilyIndexCount;
170 		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
171 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
172 	};
173 	return imageInfo;
174 }
175 
makeImageView(const DeviceInterface & vk,const VkDevice device,const VkImage image,const VkImageViewType viewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)176 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
177 								 const VkDevice					device,
178 								 const VkImage					image,
179 								 const VkImageViewType			viewType,
180 								 const VkFormat					format,
181 								 const VkImageSubresourceRange	subresourceRange)
182 {
183 	const VkImageViewCreateInfo imageViewParams =
184 	{
185 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
186 		DE_NULL,										// const void*				pNext;
187 		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
188 		image,											// VkImage					image;
189 		viewType,										// VkImageViewType			viewType;
190 		format,											// VkFormat					format;
191 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
192 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
193 	};
194 	return createImageView(vk, device, &imageViewParams);
195 }
196 
makeBufferImageCopy(const VkImageSubresourceLayers subresourceLayers,const VkExtent3D extent)197 VkBufferImageCopy makeBufferImageCopy (const VkImageSubresourceLayers	subresourceLayers,
198 									   const VkExtent3D					extent)
199 {
200 	const VkBufferImageCopy copyParams =
201 	{
202 		0ull,										//	VkDeviceSize				bufferOffset;
203 		0u,											//	deUint32					bufferRowLength;
204 		0u,											//	deUint32					bufferImageHeight;
205 		subresourceLayers,							//	VkImageSubresourceLayers	imageSubresource;
206 		makeOffset3D(0, 0, 0),						//	VkOffset3D					imageOffset;
207 		extent,										//	VkExtent3D					imageExtent;
208 	};
209 	return copyParams;
210 }
211 
beginRenderPassWithRasterizationDisabled(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer)212 void beginRenderPassWithRasterizationDisabled (const DeviceInterface&	vk,
213 											   const VkCommandBuffer	commandBuffer,
214 											   const VkRenderPass		renderPass,
215 											   const VkFramebuffer		framebuffer)
216 {
217 	const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }};
218 
219 	beginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea);
220 }
221 
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const VkImageView colorAttachment,const deUint32 width,const deUint32 height,const deUint32 layers)222 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
223 									 const VkDevice				device,
224 									 const VkRenderPass			renderPass,
225 									 const VkImageView			colorAttachment,
226 									 const deUint32				width,
227 									 const deUint32				height,
228 									 const deUint32				layers)
229 {
230 	const VkFramebufferCreateInfo framebufferInfo = {
231 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
232 		DE_NULL,										// const void*                                 pNext;
233 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
234 		renderPass,										// VkRenderPass                                renderPass;
235 		1u,												// uint32_t                                    attachmentCount;
236 		&colorAttachment,								// const VkImageView*                          pAttachments;
237 		width,											// uint32_t                                    width;
238 		height,											// uint32_t                                    height;
239 		layers,											// uint32_t                                    layers;
240 	};
241 
242 	return createFramebuffer(vk, device, &framebufferInfo);
243 }
244 
setShader(const DeviceInterface & vk,const VkDevice device,const VkShaderStageFlagBits stage,const ProgramBinary & binary,const VkSpecializationInfo * specInfo)245 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
246 															 const VkDevice					device,
247 															 const VkShaderStageFlagBits	stage,
248 															 const ProgramBinary&			binary,
249 															 const VkSpecializationInfo*	specInfo)
250 {
251 	VkShaderModule module;
252 	switch (stage)
253 	{
254 		case (VK_SHADER_STAGE_VERTEX_BIT):
255 			DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
256 			m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
257 			module = *m_vertexShaderModule;
258 			break;
259 
260 		case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
261 			DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
262 			m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
263 			module = *m_tessControlShaderModule;
264 			break;
265 
266 		case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
267 			DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
268 			m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
269 			module = *m_tessEvaluationShaderModule;
270 			break;
271 
272 		case (VK_SHADER_STAGE_GEOMETRY_BIT):
273 			DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
274 			m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
275 			module = *m_geometryShaderModule;
276 			break;
277 
278 		case (VK_SHADER_STAGE_FRAGMENT_BIT):
279 			DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
280 			m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
281 			module = *m_fragmentShaderModule;
282 			break;
283 
284 		default:
285 			DE_FATAL("Invalid shader stage");
286 			return *this;
287 	}
288 
289 	const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
290 	{
291 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
292 		DE_NULL,												// const void*							pNext;
293 		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
294 		stage,													// VkShaderStageFlagBits				stage;
295 		module,													// VkShaderModule						module;
296 		"main",													// const char*							pName;
297 		specInfo,												// const VkSpecializationInfo*			pSpecializationInfo;
298 	};
299 
300 	m_shaderStageFlags |= stage;
301 	m_shaderStages.push_back(pipelineShaderStageInfo);
302 
303 	return *this;
304 }
305 
setVertexInputSingleAttribute(const VkFormat vertexFormat,const deUint32 stride)306 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
307 {
308 	const VkVertexInputBindingDescription bindingDesc =
309 	{
310 		0u,									// uint32_t				binding;
311 		stride,								// uint32_t				stride;
312 		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
313 	};
314 	const VkVertexInputAttributeDescription attributeDesc =
315 	{
316 		0u,									// uint32_t			location;
317 		0u,									// uint32_t			binding;
318 		vertexFormat,						// VkFormat			format;
319 		0u,									// uint32_t			offset;
320 	};
321 
322 	m_vertexInputBindings.clear();
323 	m_vertexInputBindings.push_back(bindingDesc);
324 
325 	m_vertexInputAttributes.clear();
326 	m_vertexInputAttributes.push_back(attributeDesc);
327 
328 	return *this;
329 }
330 
331 template<typename T>
dataPointer(const std::vector<T> & vec)332 inline const T* dataPointer (const std::vector<T>& vec)
333 {
334 	return (vec.size() != 0 ? &vec[0] : DE_NULL);
335 }
336 
build(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,PipelineCacheData & pipelineCacheData)337 Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&	vk,
338 												 const VkDevice			device,
339 												 const VkPipelineLayout	pipelineLayout,
340 												 const VkRenderPass		renderPass,
341 												 PipelineCacheData&		pipelineCacheData)
342 {
343 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
344 	{
345 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
346 		DE_NULL,														// const void*                                 pNext;
347 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
348 		static_cast<deUint32>(m_vertexInputBindings.size()),			// uint32_t                                    vertexBindingDescriptionCount;
349 		dataPointer(m_vertexInputBindings),								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
350 		static_cast<deUint32>(m_vertexInputAttributes.size()),			// uint32_t                                    vertexAttributeDescriptionCount;
351 		dataPointer(m_vertexInputAttributes),							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
352 	};
353 
354 	const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
355 																										 : m_primitiveTopology;
356 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
357 	{
358 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
359 		DE_NULL,														// const void*                                 pNext;
360 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
361 		topology,														// VkPrimitiveTopology                         topology;
362 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
363 	};
364 
365 	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
366 	{
367 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
368 		DE_NULL,														// const void*                                 pNext;
369 		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags      flags;
370 		m_patchControlPoints,											// uint32_t                                    patchControlPoints;
371 	};
372 
373 	const VkViewport	viewport	= makeViewport(m_renderSize);
374 	const VkRect2D		scissor		= makeRect2D(m_renderSize);
375 
376 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
377 	{
378 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
379 		DE_NULL,												// const void*                                 pNext;
380 		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
381 		1u,														// uint32_t                                    viewportCount;
382 		&viewport,												// const VkViewport*                           pViewports;
383 		1u,														// uint32_t                                    scissorCount;
384 		&scissor,												// const VkRect2D*                             pScissors;
385 	};
386 
387 	const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
388 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
389 	{
390 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
391 		DE_NULL,														// const void*                              pNext;
392 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
393 		VK_FALSE,														// VkBool32                                 depthClampEnable;
394 		isRasterizationDisabled,										// VkBool32                                 rasterizerDiscardEnable;
395 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
396 		m_cullModeFlags,												// VkCullModeFlags							cullMode;
397 		m_frontFace,													// VkFrontFace								frontFace;
398 		VK_FALSE,														// VkBool32									depthBiasEnable;
399 		0.0f,															// float									depthBiasConstantFactor;
400 		0.0f,															// float									depthBiasClamp;
401 		0.0f,															// float									depthBiasSlopeFactor;
402 		1.0f,															// float									lineWidth;
403 	};
404 
405 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
406 	{
407 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
408 		DE_NULL,													// const void*								pNext;
409 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
410 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
411 		VK_FALSE,													// VkBool32									sampleShadingEnable;
412 		0.0f,														// float									minSampleShading;
413 		DE_NULL,													// const VkSampleMask*						pSampleMask;
414 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
415 		VK_FALSE													// VkBool32									alphaToOneEnable;
416 	};
417 
418 	const VkStencilOpState stencilOpState = makeStencilOpState(
419 		VK_STENCIL_OP_KEEP,		// stencil fail
420 		VK_STENCIL_OP_KEEP,		// depth & stencil pass
421 		VK_STENCIL_OP_KEEP,		// depth only fail
422 		VK_COMPARE_OP_NEVER,	// compare op
423 		0u,						// compare mask
424 		0u,						// write mask
425 		0u);					// reference
426 
427 	const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
428 	{
429 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
430 		DE_NULL,													// const void*								pNext;
431 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
432 		VK_FALSE,													// VkBool32									depthTestEnable;
433 		VK_FALSE,													// VkBool32									depthWriteEnable;
434 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
435 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
436 		VK_FALSE,													// VkBool32									stencilTestEnable;
437 		stencilOpState,												// VkStencilOpState							front;
438 		stencilOpState,												// VkStencilOpState							back;
439 		0.0f,														// float									minDepthBounds;
440 		1.0f,														// float									maxDepthBounds;
441 	};
442 
443 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
444 	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
445 	{
446 		m_blendEnable,						// VkBool32					blendEnable;
447 		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
448 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
449 		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
450 		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
451 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
452 		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
453 		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
454 	};
455 
456 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
457 	{
458 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
459 		DE_NULL,													// const void*									pNext;
460 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
461 		VK_FALSE,													// VkBool32										logicOpEnable;
462 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
463 		1u,															// deUint32										attachmentCount;
464 		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
465 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
466 	};
467 
468 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
469 	{
470 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,						// VkStructureType									sType;
471 		DE_NULL,																// const void*										pNext;
472 		(VkPipelineCreateFlags)0,												// VkPipelineCreateFlags							flags;
473 		static_cast<deUint32>(m_shaderStages.size()),							// deUint32											stageCount;
474 		&m_shaderStages[0],														// const VkPipelineShaderStageCreateInfo*			pStages;
475 		&vertexInputStateInfo,													// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
476 		&pipelineInputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
477 		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
478 		(isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),		// const VkPipelineViewportStateCreateInfo*			pViewportState;
479 		&pipelineRasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
480 		(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),	// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
481 		(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),	// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
482 		(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),		// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
483 		DE_NULL,																// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
484 		pipelineLayout,															// VkPipelineLayout									layout;
485 		renderPass,																// VkRenderPass										renderPass;
486 		0u,																		// deUint32											subpass;
487 		DE_NULL,																// VkPipeline										basePipelineHandle;
488 		0,																		// deInt32											basePipelineIndex;
489 	};
490 
491 	{
492 		const vk::Unique<vk::VkPipelineCache>	pipelineCache	(pipelineCacheData.createPipelineCache(vk, device));
493 		vk::Move<vk::VkPipeline>				pipeline		(createGraphicsPipeline(vk, device, *pipelineCache, &graphicsPipelineInfo));
494 
495 		// Refresh data from cache
496 		pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
497 
498 		return pipeline;
499 	}
500 }
501 
requireFeatures(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const FeatureFlags flags)502 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
503 {
504 	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
505 
506 	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
507 		throw tcu::NotSupportedError("Tessellation shader not supported");
508 
509 	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
510 		throw tcu::NotSupportedError("Geometry shader not supported");
511 
512 	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
513 		throw tcu::NotSupportedError("Double-precision floats not supported");
514 
515 	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
516 		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
517 
518 	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
519 		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
520 
521 	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
522 		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
523 
524 	if (((flags & FEATURE_SHADER_STORAGE_IMAGE_EXTENDED_FORMATS) != 0) && !features.shaderStorageImageExtendedFormats)
525 		throw tcu::NotSupportedError("Storage image extended formats not supported");
526 }
527 
getResourceName(const ResourceDescription & resource)528 std::string getResourceName (const ResourceDescription& resource)
529 {
530 	std::ostringstream str;
531 
532 	if (resource.type == RESOURCE_TYPE_BUFFER)
533 		str << "buffer_" << resource.size.x();
534 	else if (resource.type == RESOURCE_TYPE_IMAGE)
535 	{
536 		str << "image_" << resource.size.x()
537 						<< (resource.size.y() > 0 ? "x" + de::toString(resource.size.y()) : "")
538 						<< (resource.size.z() > 0 ? "x" + de::toString(resource.size.z()) : "")
539 			<< "_" << de::toLower(getFormatName(resource.imageFormat)).substr(10);
540 	}
541 	else if (isIndirectBuffer(resource.type))
542 		str << "indirect_buffer";
543 	else
544 		DE_ASSERT(0);
545 
546 	return str.str();
547 }
548 
isIndirectBuffer(const ResourceType type)549 bool isIndirectBuffer (const ResourceType type)
550 {
551 	switch (type)
552 	{
553 		case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
554 		case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
555 		case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
556 			return true;
557 
558 		default:
559 			return false;
560 	}
561 }
562 
PipelineCacheData(void)563 PipelineCacheData::PipelineCacheData (void)
564 {
565 }
566 
~PipelineCacheData(void)567 PipelineCacheData::~PipelineCacheData (void)
568 {
569 }
570 
createPipelineCache(const vk::DeviceInterface & vk,const vk::VkDevice device) const571 vk::Move<VkPipelineCache> PipelineCacheData::createPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device) const
572 {
573 	const de::ScopedLock						dataLock	(m_lock);
574 	const struct vk::VkPipelineCacheCreateInfo	params	=
575 	{
576 		vk::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
577 		DE_NULL,
578 		(vk::VkPipelineCacheCreateFlags)0,
579 		(deUintptr)m_data.size(),
580 		(m_data.empty() ? DE_NULL : &m_data[0])
581 	};
582 
583 	return vk::createPipelineCache(vk, device, &params);
584 }
585 
setFromPipelineCache(const vk::DeviceInterface & vk,const vk::VkDevice device,const vk::VkPipelineCache pipelineCache)586 void PipelineCacheData::setFromPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineCache pipelineCache)
587 {
588 	const de::ScopedLock		dataLock		(m_lock);
589 	deUintptr					dataSize		= 0;
590 
591 	VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, DE_NULL));
592 
593 	m_data.resize(dataSize);
594 
595 	if (dataSize > 0)
596 		VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, &m_data[0]));
597 }
598 
599 } // synchronization
600 } // vkt
601