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 "deStringUtil.hpp"
27
28namespace vkt
29{
30namespace synchronization
31{
32using namespace vk;
33
34VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
35										 const VkBufferUsageFlags	usage)
36{
37	const VkBufferCreateInfo bufferCreateInfo =
38	{
39		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
40		DE_NULL,								// const void*			pNext;
41		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
42		bufferSize,								// VkDeviceSize			size;
43		usage,									// VkBufferUsageFlags	usage;
44		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
45		0u,										// deUint32				queueFamilyIndexCount;
46		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
47	};
48	return bufferCreateInfo;
49}
50
51VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags	srcAccessMask,
52								   const VkAccessFlags	dstAccessMask)
53{
54	const VkMemoryBarrier barrier =
55	{
56		VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// VkStructureType    sType;
57		DE_NULL,							// const void*        pNext;
58		srcAccessMask,						// VkAccessFlags      srcAccessMask;
59		dstAccessMask,						// VkAccessFlags      dstAccessMask;
60	};
61	return barrier;
62}
63
64VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
65											   const VkAccessFlags	dstAccessMask,
66											   const VkBuffer		buffer,
67											   const VkDeviceSize	offset,
68											   const VkDeviceSize	bufferSizeBytes)
69{
70	const VkBufferMemoryBarrier barrier =
71	{
72		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
73		DE_NULL,									// const void*		pNext;
74		srcAccessMask,								// VkAccessFlags	srcAccessMask;
75		dstAccessMask,								// VkAccessFlags	dstAccessMask;
76		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
77		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex;
78		buffer,										// VkBuffer			buffer;
79		offset,										// VkDeviceSize		offset;
80		bufferSizeBytes,							// VkDeviceSize		size;
81	};
82	return barrier;
83}
84
85VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
86											 const VkAccessFlags			dstAccessMask,
87											 const VkImageLayout			oldLayout,
88											 const VkImageLayout			newLayout,
89											 const VkImage					image,
90											 const VkImageSubresourceRange	subresourceRange)
91{
92	const VkImageMemoryBarrier barrier =
93	{
94		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
95		DE_NULL,										// const void*				pNext;
96		srcAccessMask,									// VkAccessFlags			outputMask;
97		dstAccessMask,									// VkAccessFlags			inputMask;
98		oldLayout,										// VkImageLayout			oldLayout;
99		newLayout,										// VkImageLayout			newLayout;
100		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
101		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
102		image,											// VkImage					image;
103		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
104	};
105	return barrier;
106}
107
108Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
109{
110	const VkCommandBufferAllocateInfo info =
111	{
112		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
113		DE_NULL,											// const void*			pNext;
114		commandPool,										// VkCommandPool		commandPool;
115		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
116		1u,													// deUint32				commandBufferCount;
117	};
118	return allocateCommandBuffer(vk, device, &info);
119}
120
121Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
122										 const VkDevice					device,
123										 const VkDescriptorPool			descriptorPool,
124										 const VkDescriptorSetLayout	setLayout)
125{
126	const VkDescriptorSetAllocateInfo info =
127	{
128		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
129		DE_NULL,											// const void*					pNext;
130		descriptorPool,										// VkDescriptorPool				descriptorPool;
131		1u,													// deUint32						descriptorSetCount;
132		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
133	};
134	return allocateDescriptorSet(vk, device, &info);
135}
136
137Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
138										   const VkDevice				device,
139										   const VkDescriptorSetLayout	descriptorSetLayout)
140{
141	const VkPipelineLayoutCreateInfo info =
142	{
143		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
144		DE_NULL,											// const void*					pNext;
145		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
146		1u,													// deUint32						setLayoutCount;
147		&descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
148		0u,													// deUint32						pushConstantRangeCount;
149		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
150	};
151	return createPipelineLayout(vk, device, &info);
152}
153
154Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&		vk,
155															 const VkDevice				device)
156{
157	const VkPipelineLayoutCreateInfo info =
158	{
159		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
160		DE_NULL,											// const void*					pNext;
161		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
162		0u,													// deUint32						setLayoutCount;
163		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
164		0u,													// deUint32						pushConstantRangeCount;
165		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
166	};
167	return createPipelineLayout(vk, device, &info);
168}
169
170Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
171									  const VkDevice				device,
172									  const VkPipelineLayout		pipelineLayout,
173									  const VkShaderModule			shaderModule,
174									  const VkSpecializationInfo*	specInfo,
175									  PipelineCacheData&			pipelineCacheData)
176{
177	const VkPipelineShaderStageCreateInfo shaderStageInfo =
178	{
179		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
180		DE_NULL,												// const void*						pNext;
181		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags	flags;
182		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
183		shaderModule,											// VkShaderModule					module;
184		"main",													// const char*						pName;
185		specInfo,												// const VkSpecializationInfo*		pSpecializationInfo;
186	};
187	const VkComputePipelineCreateInfo pipelineInfo =
188	{
189		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
190		DE_NULL,											// const void*						pNext;
191		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags			flags;
192		shaderStageInfo,									// VkPipelineShaderStageCreateInfo	stage;
193		pipelineLayout,										// VkPipelineLayout					layout;
194		DE_NULL,											// VkPipeline						basePipelineHandle;
195		0,													// deInt32							basePipelineIndex;
196	};
197
198	{
199		const vk::Unique<vk::VkPipelineCache>	pipelineCache	(pipelineCacheData.createPipelineCache(vk, device));
200		vk::Move<vk::VkPipeline>				pipeline		(createComputePipeline(vk, device, *pipelineCache, &pipelineInfo));
201
202		// Refresh data from cache
203		pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
204
205		return pipeline;
206	}
207}
208
209VkImageCreateInfo makeImageCreateInfo (const VkImageType imageType, const VkExtent3D& extent, const VkFormat format, const VkImageUsageFlags usage)
210{
211	const VkImageCreateInfo imageInfo =
212	{
213		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
214		DE_NULL,									// const void*              pNext;
215		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
216		imageType,									// VkImageType              imageType;
217		format,										// VkFormat                 format;
218		extent,										// VkExtent3D               extent;
219		1u,											// uint32_t                 mipLevels;
220		1u,											// uint32_t                 arrayLayers;
221		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
222		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
223		usage,										// VkImageUsageFlags        usage;
224		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
225		0u,											// uint32_t                 queueFamilyIndexCount;
226		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
227		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
228	};
229	return imageInfo;
230}
231
232Move<VkImageView> makeImageView (const DeviceInterface&			vk,
233								 const VkDevice					device,
234								 const VkImage					image,
235								 const VkImageViewType			viewType,
236								 const VkFormat					format,
237								 const VkImageSubresourceRange	subresourceRange)
238{
239	const VkImageViewCreateInfo imageViewParams =
240	{
241		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
242		DE_NULL,										// const void*				pNext;
243		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
244		image,											// VkImage					image;
245		viewType,										// VkImageViewType			viewType;
246		format,											// VkFormat					format;
247		makeComponentMappingRGBA(),						// VkComponentMapping		components;
248		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
249	};
250	return createImageView(vk, device, &imageViewParams);
251}
252
253VkBufferImageCopy makeBufferImageCopy (const VkImageSubresourceLayers	subresourceLayers,
254									   const VkExtent3D					extent)
255{
256	const VkBufferImageCopy copyParams =
257	{
258		0ull,										//	VkDeviceSize				bufferOffset;
259		0u,											//	deUint32					bufferRowLength;
260		0u,											//	deUint32					bufferImageHeight;
261		subresourceLayers,							//	VkImageSubresourceLayers	imageSubresource;
262		makeOffset3D(0, 0, 0),						//	VkOffset3D					imageOffset;
263		extent,										//	VkExtent3D					imageExtent;
264	};
265	return copyParams;
266}
267
268void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
269{
270	const VkCommandBufferBeginInfo info =
271	{
272		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
273		DE_NULL,										// const void*                              pNext;
274		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags                flags;
275		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
276	};
277	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
278}
279
280void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
281{
282	VK_CHECK(vk.endCommandBuffer(commandBuffer));
283}
284
285void submitCommandsAndWait (const DeviceInterface&	vk,
286							const VkDevice			device,
287							const VkQueue			queue,
288							const VkCommandBuffer	commandBuffer)
289{
290	const Unique<VkFence> fence(createFence(vk, device));
291
292	const VkSubmitInfo submitInfo =
293	{
294		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType                sType;
295		DE_NULL,							// const void*                    pNext;
296		0u,									// uint32_t                       waitSemaphoreCount;
297		DE_NULL,							// const VkSemaphore*             pWaitSemaphores;
298		DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
299		1u,									// uint32_t                       commandBufferCount;
300		&commandBuffer,						// const VkCommandBuffer*         pCommandBuffers;
301		0u,									// uint32_t                       signalSemaphoreCount;
302		DE_NULL,							// const VkSemaphore*             pSignalSemaphores;
303	};
304	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
305	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
306}
307
308void beginRenderPass (const DeviceInterface&	vk,
309					  const VkCommandBuffer		commandBuffer,
310					  const VkRenderPass		renderPass,
311					  const VkFramebuffer		framebuffer,
312					  const VkRect2D&			renderArea,
313					  const tcu::Vec4&			clearColor)
314{
315	const VkClearValue clearValue = makeClearValueColor(clearColor);
316
317	const VkRenderPassBeginInfo renderPassBeginInfo = {
318		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
319		DE_NULL,										// const void*             pNext;
320		renderPass,										// VkRenderPass            renderPass;
321		framebuffer,									// VkFramebuffer           framebuffer;
322		renderArea,										// VkRect2D                renderArea;
323		1u,												// uint32_t                clearValueCount;
324		&clearValue,									// const VkClearValue*     pClearValues;
325	};
326
327	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
328}
329
330void beginRenderPassWithRasterizationDisabled (const DeviceInterface&	vk,
331											   const VkCommandBuffer	commandBuffer,
332											   const VkRenderPass		renderPass,
333											   const VkFramebuffer		framebuffer)
334{
335	const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }};
336
337	const VkRenderPassBeginInfo renderPassBeginInfo = {
338		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
339		DE_NULL,										// const void*             pNext;
340		renderPass,										// VkRenderPass            renderPass;
341		framebuffer,									// VkFramebuffer           framebuffer;
342		renderArea,										// VkRect2D                renderArea;
343		0u,												// uint32_t                clearValueCount;
344		DE_NULL,										// const VkClearValue*     pClearValues;
345	};
346
347	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
348}
349
350void endRenderPass (const DeviceInterface&	vk,
351					const VkCommandBuffer	commandBuffer)
352{
353	vk.cmdEndRenderPass(commandBuffer);
354}
355
356Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
357								   const VkDevice			device,
358								   const VkFormat			colorFormat)
359{
360	const VkAttachmentDescription colorAttachmentDescription =
361	{
362		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
363		colorFormat,										// VkFormat							format;
364		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
365		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
366		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
367		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
368		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
369		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
370		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
371	};
372
373	const VkAttachmentReference colorAttachmentReference =
374	{
375		0u,													// deUint32			attachment;
376		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
377	};
378
379	const VkAttachmentReference depthAttachmentReference =
380	{
381		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
382		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
383	};
384
385	const VkSubpassDescription subpassDescription =
386	{
387		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
388		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
389		0u,													// deUint32							inputAttachmentCount;
390		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
391		1u,													// deUint32							colorAttachmentCount;
392		&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
393		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
394		&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
395		0u,													// deUint32							preserveAttachmentCount;
396		DE_NULL												// const deUint32*					pPreserveAttachments;
397	};
398
399	const VkRenderPassCreateInfo renderPassInfo =
400	{
401		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
402		DE_NULL,											// const void*						pNext;
403		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
404		1u,													// deUint32							attachmentCount;
405		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
406		1u,													// deUint32							subpassCount;
407		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
408		0u,													// deUint32							dependencyCount;
409		DE_NULL												// const VkSubpassDependency*		pDependencies;
410	};
411
412	return createRenderPass(vk, device, &renderPassInfo);
413}
414
415Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
416									 const VkDevice				device,
417									 const VkRenderPass			renderPass,
418									 const VkImageView			colorAttachment,
419									 const deUint32				width,
420									 const deUint32				height,
421									 const deUint32				layers)
422{
423	const VkFramebufferCreateInfo framebufferInfo = {
424		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
425		DE_NULL,										// const void*                                 pNext;
426		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
427		renderPass,										// VkRenderPass                                renderPass;
428		1u,												// uint32_t                                    attachmentCount;
429		&colorAttachment,								// const VkImageView*                          pAttachments;
430		width,											// uint32_t                                    width;
431		height,											// uint32_t                                    height;
432		layers,											// uint32_t                                    layers;
433	};
434
435	return createFramebuffer(vk, device, &framebufferInfo);
436}
437
438GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
439															 const VkDevice					device,
440															 const VkShaderStageFlagBits	stage,
441															 const ProgramBinary&			binary,
442															 const VkSpecializationInfo*	specInfo)
443{
444	VkShaderModule module;
445	switch (stage)
446	{
447		case (VK_SHADER_STAGE_VERTEX_BIT):
448			DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
449			m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
450			module = *m_vertexShaderModule;
451			break;
452
453		case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
454			DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
455			m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
456			module = *m_tessControlShaderModule;
457			break;
458
459		case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
460			DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
461			m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
462			module = *m_tessEvaluationShaderModule;
463			break;
464
465		case (VK_SHADER_STAGE_GEOMETRY_BIT):
466			DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
467			m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
468			module = *m_geometryShaderModule;
469			break;
470
471		case (VK_SHADER_STAGE_FRAGMENT_BIT):
472			DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
473			m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
474			module = *m_fragmentShaderModule;
475			break;
476
477		default:
478			DE_FATAL("Invalid shader stage");
479			return *this;
480	}
481
482	const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
483	{
484		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
485		DE_NULL,												// const void*							pNext;
486		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
487		stage,													// VkShaderStageFlagBits				stage;
488		module,													// VkShaderModule						module;
489		"main",													// const char*							pName;
490		specInfo,												// const VkSpecializationInfo*			pSpecializationInfo;
491	};
492
493	m_shaderStageFlags |= stage;
494	m_shaderStages.push_back(pipelineShaderStageInfo);
495
496	return *this;
497}
498
499GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
500{
501	const VkVertexInputBindingDescription bindingDesc =
502	{
503		0u,									// uint32_t				binding;
504		stride,								// uint32_t				stride;
505		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
506	};
507	const VkVertexInputAttributeDescription attributeDesc =
508	{
509		0u,									// uint32_t			location;
510		0u,									// uint32_t			binding;
511		vertexFormat,						// VkFormat			format;
512		0u,									// uint32_t			offset;
513	};
514
515	m_vertexInputBindings.clear();
516	m_vertexInputBindings.push_back(bindingDesc);
517
518	m_vertexInputAttributes.clear();
519	m_vertexInputAttributes.push_back(attributeDesc);
520
521	return *this;
522}
523
524template<typename T>
525inline const T* dataPointer (const std::vector<T>& vec)
526{
527	return (vec.size() != 0 ? &vec[0] : DE_NULL);
528}
529
530Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&	vk,
531												 const VkDevice			device,
532												 const VkPipelineLayout	pipelineLayout,
533												 const VkRenderPass		renderPass,
534												 PipelineCacheData&		pipelineCacheData)
535{
536	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
537	{
538		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
539		DE_NULL,														// const void*                                 pNext;
540		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
541		static_cast<deUint32>(m_vertexInputBindings.size()),			// uint32_t                                    vertexBindingDescriptionCount;
542		dataPointer(m_vertexInputBindings),								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
543		static_cast<deUint32>(m_vertexInputAttributes.size()),			// uint32_t                                    vertexAttributeDescriptionCount;
544		dataPointer(m_vertexInputAttributes),							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
545	};
546
547	const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
548																										 : m_primitiveTopology;
549	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
550	{
551		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
552		DE_NULL,														// const void*                                 pNext;
553		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
554		topology,														// VkPrimitiveTopology                         topology;
555		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
556	};
557
558	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
559	{
560		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
561		DE_NULL,														// const void*                                 pNext;
562		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags      flags;
563		m_patchControlPoints,											// uint32_t                                    patchControlPoints;
564	};
565
566	const VkViewport viewport = makeViewport(
567		0.0f, 0.0f,
568		static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
569		0.0f, 1.0f);
570
571	const VkRect2D scissor = {
572		makeOffset2D(0, 0),
573		makeExtent2D(m_renderSize.x(), m_renderSize.y()),
574	};
575
576	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
577	{
578		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
579		DE_NULL,												// const void*                                 pNext;
580		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
581		1u,														// uint32_t                                    viewportCount;
582		&viewport,												// const VkViewport*                           pViewports;
583		1u,														// uint32_t                                    scissorCount;
584		&scissor,												// const VkRect2D*                             pScissors;
585	};
586
587	const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
588	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
589	{
590		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
591		DE_NULL,														// const void*                              pNext;
592		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
593		VK_FALSE,														// VkBool32                                 depthClampEnable;
594		isRasterizationDisabled,										// VkBool32                                 rasterizerDiscardEnable;
595		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
596		m_cullModeFlags,												// VkCullModeFlags							cullMode;
597		m_frontFace,													// VkFrontFace								frontFace;
598		VK_FALSE,														// VkBool32									depthBiasEnable;
599		0.0f,															// float									depthBiasConstantFactor;
600		0.0f,															// float									depthBiasClamp;
601		0.0f,															// float									depthBiasSlopeFactor;
602		1.0f,															// float									lineWidth;
603	};
604
605	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
606	{
607		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
608		DE_NULL,													// const void*								pNext;
609		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
610		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
611		VK_FALSE,													// VkBool32									sampleShadingEnable;
612		0.0f,														// float									minSampleShading;
613		DE_NULL,													// const VkSampleMask*						pSampleMask;
614		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
615		VK_FALSE													// VkBool32									alphaToOneEnable;
616	};
617
618	const VkStencilOpState stencilOpState = makeStencilOpState(
619		VK_STENCIL_OP_KEEP,		// stencil fail
620		VK_STENCIL_OP_KEEP,		// depth & stencil pass
621		VK_STENCIL_OP_KEEP,		// depth only fail
622		VK_COMPARE_OP_NEVER,	// compare op
623		0u,						// compare mask
624		0u,						// write mask
625		0u);					// reference
626
627	const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
628	{
629		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
630		DE_NULL,													// const void*								pNext;
631		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
632		VK_FALSE,													// VkBool32									depthTestEnable;
633		VK_FALSE,													// VkBool32									depthWriteEnable;
634		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
635		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
636		VK_FALSE,													// VkBool32									stencilTestEnable;
637		stencilOpState,												// VkStencilOpState							front;
638		stencilOpState,												// VkStencilOpState							back;
639		0.0f,														// float									minDepthBounds;
640		1.0f,														// float									maxDepthBounds;
641	};
642
643	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
644	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
645	{
646		m_blendEnable,						// VkBool32					blendEnable;
647		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
648		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
649		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
650		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
651		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
652		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
653		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
654	};
655
656	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
657	{
658		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
659		DE_NULL,													// const void*									pNext;
660		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
661		VK_FALSE,													// VkBool32										logicOpEnable;
662		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
663		1u,															// deUint32										attachmentCount;
664		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
665		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
666	};
667
668	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
669	{
670		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,						// VkStructureType									sType;
671		DE_NULL,																// const void*										pNext;
672		(VkPipelineCreateFlags)0,												// VkPipelineCreateFlags							flags;
673		static_cast<deUint32>(m_shaderStages.size()),							// deUint32											stageCount;
674		&m_shaderStages[0],														// const VkPipelineShaderStageCreateInfo*			pStages;
675		&vertexInputStateInfo,													// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
676		&pipelineInputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
677		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
678		(isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),		// const VkPipelineViewportStateCreateInfo*			pViewportState;
679		&pipelineRasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
680		(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),	// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
681		(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),	// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
682		(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),		// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
683		DE_NULL,																// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
684		pipelineLayout,															// VkPipelineLayout									layout;
685		renderPass,																// VkRenderPass										renderPass;
686		0u,																		// deUint32											subpass;
687		DE_NULL,																// VkPipeline										basePipelineHandle;
688		0,																		// deInt32											basePipelineIndex;
689	};
690
691	{
692		const vk::Unique<vk::VkPipelineCache>	pipelineCache	(pipelineCacheData.createPipelineCache(vk, device));
693		vk::Move<vk::VkPipeline>				pipeline		(createGraphicsPipeline(vk, device, *pipelineCache, &graphicsPipelineInfo));
694
695		// Refresh data from cache
696		pipelineCacheData.setFromPipelineCache(vk, device, *pipelineCache);
697
698		return pipeline;
699	}
700}
701
702void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
703{
704	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
705
706	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
707		throw tcu::NotSupportedError("Tessellation shader not supported");
708
709	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
710		throw tcu::NotSupportedError("Geometry shader not supported");
711
712	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
713		throw tcu::NotSupportedError("Double-precision floats not supported");
714
715	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
716		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
717
718	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
719		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
720
721	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
722		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
723
724	if (((flags & FEATURE_SHADER_STORAGE_IMAGE_EXTENDED_FORMATS) != 0) && !features.shaderStorageImageExtendedFormats)
725		throw tcu::NotSupportedError("Storage image extended formats not supported");
726}
727
728std::string getResourceName (const ResourceDescription& resource)
729{
730	std::ostringstream str;
731
732	if (resource.type == RESOURCE_TYPE_BUFFER)
733		str << "buffer_" << resource.size.x();
734	else if (resource.type == RESOURCE_TYPE_IMAGE)
735	{
736		str << "image_" << resource.size.x()
737						<< (resource.size.y() > 0 ? "x" + de::toString(resource.size.y()) : "")
738						<< (resource.size.z() > 0 ? "x" + de::toString(resource.size.z()) : "")
739			<< "_" << de::toLower(getFormatName(resource.imageFormat)).substr(10);
740	}
741	else if (isIndirectBuffer(resource.type))
742		str << "indirect_buffer";
743	else
744		DE_ASSERT(0);
745
746	return str.str();
747}
748
749bool isIndirectBuffer (const ResourceType type)
750{
751	switch (type)
752	{
753		case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW:
754		case RESOURCE_TYPE_INDIRECT_BUFFER_DRAW_INDEXED:
755		case RESOURCE_TYPE_INDIRECT_BUFFER_DISPATCH:
756			return true;
757
758		default:
759			return false;
760	}
761}
762
763PipelineCacheData::PipelineCacheData (void)
764{
765}
766
767PipelineCacheData::~PipelineCacheData (void)
768{
769}
770
771vk::Move<VkPipelineCache> PipelineCacheData::createPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device) const
772{
773	const de::ScopedLock						dataLock	(m_lock);
774	const struct vk::VkPipelineCacheCreateInfo	params	=
775	{
776		vk::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
777		DE_NULL,
778		(vk::VkPipelineCacheCreateFlags)0,
779		(deUintptr)m_data.size(),
780		(m_data.empty() ? DE_NULL : &m_data[0])
781	};
782
783	return vk::createPipelineCache(vk, device, &params);
784}
785
786void PipelineCacheData::setFromPipelineCache (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineCache pipelineCache)
787{
788	const de::ScopedLock		dataLock		(m_lock);
789	deUintptr					dataSize		= 0;
790
791	VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, DE_NULL));
792
793	m_data.resize(dataSize);
794
795	if (dataSize > 0)
796		VK_CHECK(vk.getPipelineCacheData(device, pipelineCache, &dataSize, &m_data[0]));
797}
798
799} // synchronization
800} // vkt
801