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 Pipeline specialization constants test utilities
22 *//*--------------------------------------------------------------------*/
23
24#include "vktPipelineSpecConstantUtil.hpp"
25#include "vkTypeUtil.hpp"
26#include <vector>
27
28namespace vkt
29{
30namespace pipeline
31{
32using namespace vk;
33
34GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
35															 const VkDevice					device,
36															 const VkShaderStageFlagBits	stage,
37															 const ProgramBinary&			binary,
38															 const VkSpecializationInfo*	specInfo)
39{
40	VkShaderModule module;
41	switch (stage)
42	{
43		case (VK_SHADER_STAGE_VERTEX_BIT):
44			DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
45			m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
46			module = *m_vertexShaderModule;
47			break;
48
49		case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
50			DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
51			m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
52			module = *m_tessControlShaderModule;
53			break;
54
55		case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
56			DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
57			m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
58			module = *m_tessEvaluationShaderModule;
59			break;
60
61		case (VK_SHADER_STAGE_GEOMETRY_BIT):
62			DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
63			m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
64			module = *m_geometryShaderModule;
65			break;
66
67		case (VK_SHADER_STAGE_FRAGMENT_BIT):
68			DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
69			m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
70			module = *m_fragmentShaderModule;
71			break;
72
73		default:
74			DE_FATAL("Invalid shader stage");
75			return *this;
76	}
77
78	const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
79	{
80		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
81		DE_NULL,												// const void*							pNext;
82		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
83		stage,													// VkShaderStageFlagBits				stage;
84		module,													// VkShaderModule						module;
85		"main",													// const char*							pName;
86		specInfo,												// const VkSpecializationInfo*			pSpecializationInfo;
87	};
88
89	m_shaderStageFlags |= stage;
90	m_shaderStages.push_back(pipelineShaderStageInfo);
91
92	return *this;
93}
94
95Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&	vk,
96												 const VkDevice			device,
97												 const VkPipelineLayout	pipelineLayout,
98												 const VkRenderPass		renderPass)
99{
100	const VkVertexInputBindingDescription vertexInputBindingDescription =
101	{
102		0u,								// uint32_t				binding;
103		sizeof(tcu::Vec4),				// uint32_t				stride;		// Vertex is a 4-element vector XYZW, position only
104		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
105	};
106
107	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
108	{
109		0u,									// uint32_t			location;
110		0u,									// uint32_t			binding;
111		VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
112		0u,									// uint32_t			offset;
113	};
114
115	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
116	{
117		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType;
118		DE_NULL,													// const void*                                 pNext;
119		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags       flags;
120		1u,															// uint32_t                                    vertexBindingDescriptionCount;
121		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
122		1u,															// uint32_t                                    vertexAttributeDescriptionCount;
123		&vertexInputAttributeDescription,							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
124	};
125
126	const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
127	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
128	{
129		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
130		DE_NULL,														// const void*                                 pNext;
131		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
132		topology,														// VkPrimitiveTopology                         topology;
133		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
134	};
135
136	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
137	{
138		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
139		DE_NULL,														// const void*                                 pNext;
140		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags      flags;
141		3u,																// uint32_t                                    patchControlPoints;
142	};
143
144	const VkViewport viewport = makeViewport(
145		0.0f, 0.0f,
146		static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
147		0.0f, 1.0f);
148
149	const VkRect2D scissor = {
150		makeOffset2D(0, 0),
151		makeExtent2D(m_renderSize.x(), m_renderSize.y()),
152	};
153
154	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
155	{
156		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
157		DE_NULL,												// const void*                                 pNext;
158		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
159		1u,														// uint32_t                                    viewportCount;
160		&viewport,												// const VkViewport*                           pViewports;
161		1u,														// uint32_t                                    scissorCount;
162		&scissor,												// const VkRect2D*                             pScissors;
163	};
164
165	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
166	{
167		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
168		DE_NULL,														// const void*                              pNext;
169		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
170		VK_FALSE,														// VkBool32                                 depthClampEnable;
171		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
172		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
173		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
174		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
175		VK_FALSE,														// VkBool32									depthBiasEnable;
176		0.0f,															// float									depthBiasConstantFactor;
177		0.0f,															// float									depthBiasClamp;
178		0.0f,															// float									depthBiasSlopeFactor;
179		1.0f,															// float									lineWidth;
180	};
181
182	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
183	{
184		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
185		DE_NULL,													// const void*								pNext;
186		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
187		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
188		VK_FALSE,													// VkBool32									sampleShadingEnable;
189		0.0f,														// float									minSampleShading;
190		DE_NULL,													// const VkSampleMask*						pSampleMask;
191		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
192		VK_FALSE													// VkBool32									alphaToOneEnable;
193	};
194
195	const VkStencilOpState stencilOpStateBasic = makeStencilOpState(
196		VK_STENCIL_OP_KEEP,		// stencil fail
197		VK_STENCIL_OP_KEEP,		// depth & stencil pass
198		VK_STENCIL_OP_KEEP,		// depth only fail
199		VK_COMPARE_OP_NEVER,	// compare op
200		0u,						// compare mask
201		0u,						// write mask
202		0u);					// reference
203
204	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
205	{
206		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
207		DE_NULL,													// const void*								pNext;
208		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
209		VK_FALSE,													// VkBool32									depthTestEnable;
210		VK_FALSE,													// VkBool32									depthWriteEnable;
211		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
212		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
213		VK_FALSE,													// VkBool32									stencilTestEnable;
214		stencilOpStateBasic,										// VkStencilOpState							front;
215		stencilOpStateBasic,										// VkStencilOpState							back;
216		0.0f,														// float									minDepthBounds;
217		1.0f,														// float									maxDepthBounds;
218	};
219
220	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
221	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
222	{
223		VK_FALSE,							// VkBool32					blendEnable;
224		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcColorBlendFactor;
225		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstColorBlendFactor;
226		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
227		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcAlphaBlendFactor;
228		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstAlphaBlendFactor;
229		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
230		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
231	};
232
233	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
234	{
235		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
236		DE_NULL,													// const void*									pNext;
237		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
238		VK_FALSE,													// VkBool32										logicOpEnable;
239		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
240		1u,															// deUint32										attachmentCount;
241		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
242		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
243	};
244
245	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
246	{
247		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
248		DE_NULL,											// const void*										pNext;
249		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
250		static_cast<deUint32>(m_shaderStages.size()),		// deUint32											stageCount;
251		&m_shaderStages[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
252		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
253		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
254		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
255		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
256		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
257		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
258		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
259		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
260		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
261		pipelineLayout,										// VkPipelineLayout									layout;
262		renderPass,											// VkRenderPass										renderPass;
263		0u,													// deUint32											subpass;
264		DE_NULL,											// VkPipeline										basePipelineHandle;
265		0,													// deInt32											basePipelineIndex;
266	};
267
268	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
269}
270
271Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
272								   const VkDevice			device,
273								   const VkFormat			colorFormat)
274{
275	const VkAttachmentDescription colorAttachmentDescription =
276	{
277		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
278		colorFormat,										// VkFormat							format;
279		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
280		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
281		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
282		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
283		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
284		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
285		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
286	};
287
288	const VkAttachmentReference colorAttachmentReference =
289	{
290		0u,													// deUint32			attachment;
291		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
292	};
293
294	const VkAttachmentReference depthAttachmentReference =
295	{
296		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
297		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
298	};
299
300	const VkSubpassDescription subpassDescription =
301	{
302		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
303		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
304		0u,													// deUint32							inputAttachmentCount;
305		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
306		1u,													// deUint32							colorAttachmentCount;
307		&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
308		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
309		&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
310		0u,													// deUint32							preserveAttachmentCount;
311		DE_NULL												// const deUint32*					pPreserveAttachments;
312	};
313
314	const VkRenderPassCreateInfo renderPassInfo =
315	{
316		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
317		DE_NULL,											// const void*						pNext;
318		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
319		1u,													// deUint32							attachmentCount;
320		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
321		1u,													// deUint32							subpassCount;
322		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
323		0u,													// deUint32							dependencyCount;
324		DE_NULL												// const VkSubpassDependency*		pDependencies;
325	};
326
327	return createRenderPass(vk, device, &renderPassInfo);
328}
329
330void beginRenderPass (const DeviceInterface&	vk,
331					  const VkCommandBuffer		commandBuffer,
332					  const VkRenderPass		renderPass,
333					  const VkFramebuffer		framebuffer,
334					  const VkRect2D&			renderArea,
335					  const tcu::Vec4&			clearColor)
336{
337	const VkClearValue clearValue = makeClearValueColor(clearColor);
338
339	const VkRenderPassBeginInfo renderPassBeginInfo = {
340		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
341		DE_NULL,										// const void*             pNext;
342		renderPass,										// VkRenderPass            renderPass;
343		framebuffer,									// VkFramebuffer           framebuffer;
344		renderArea,										// VkRect2D                renderArea;
345		1u,												// uint32_t                clearValueCount;
346		&clearValue,									// const VkClearValue*     pClearValues;
347	};
348
349	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
350}
351
352VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
353{
354	const VkImageCreateInfo imageInfo =
355	{
356		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
357		DE_NULL,									// const void*              pNext;
358		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
359		VK_IMAGE_TYPE_2D,							// VkImageType              imageType;
360		format,										// VkFormat                 format;
361		makeExtent3D(size.x(), size.y(), 1),		// VkExtent3D               extent;
362		1u,											// uint32_t                 mipLevels;
363		1u,											// uint32_t                 arrayLayers;
364		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
365		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
366		usage,										// VkImageUsageFlags        usage;
367		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
368		0u,											// uint32_t                 queueFamilyIndexCount;
369		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
370		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
371	};
372	return imageInfo;
373}
374
375void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
376{
377	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
378
379	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
380		throw tcu::NotSupportedError("Tessellation shader not supported");
381
382	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
383		throw tcu::NotSupportedError("Geometry shader not supported");
384
385	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
386		throw tcu::NotSupportedError("Double-precision floats not supported");
387
388	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
389		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
390
391	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
392		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
393}
394
395} // pipeline
396} // vkt
397