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 
28 namespace vkt
29 {
30 namespace pipeline
31 {
32 using namespace vk;
33 
setShader(const DeviceInterface & vk,const VkDevice device,const VkShaderStageFlagBits stage,const ProgramBinary & binary,const VkSpecializationInfo * specInfo)34 GraphicsPipelineBuilder& 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 
build(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass)95 Move<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(m_renderSize);
145 	const VkRect2D		scissor		= makeRect2D(m_renderSize);
146 
147 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
148 	{
149 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
150 		DE_NULL,												// const void*                                 pNext;
151 		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
152 		1u,														// uint32_t                                    viewportCount;
153 		&viewport,												// const VkViewport*                           pViewports;
154 		1u,														// uint32_t                                    scissorCount;
155 		&scissor,												// const VkRect2D*                             pScissors;
156 	};
157 
158 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
159 	{
160 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
161 		DE_NULL,														// const void*                              pNext;
162 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
163 		VK_FALSE,														// VkBool32                                 depthClampEnable;
164 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
165 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
166 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
167 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
168 		VK_FALSE,														// VkBool32									depthBiasEnable;
169 		0.0f,															// float									depthBiasConstantFactor;
170 		0.0f,															// float									depthBiasClamp;
171 		0.0f,															// float									depthBiasSlopeFactor;
172 		1.0f,															// float									lineWidth;
173 	};
174 
175 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
176 	{
177 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
178 		DE_NULL,													// const void*								pNext;
179 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
180 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
181 		VK_FALSE,													// VkBool32									sampleShadingEnable;
182 		0.0f,														// float									minSampleShading;
183 		DE_NULL,													// const VkSampleMask*						pSampleMask;
184 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
185 		VK_FALSE													// VkBool32									alphaToOneEnable;
186 	};
187 
188 	const VkStencilOpState stencilOpStateBasic = makeStencilOpState(
189 		VK_STENCIL_OP_KEEP,		// stencil fail
190 		VK_STENCIL_OP_KEEP,		// depth & stencil pass
191 		VK_STENCIL_OP_KEEP,		// depth only fail
192 		VK_COMPARE_OP_NEVER,	// compare op
193 		0u,						// compare mask
194 		0u,						// write mask
195 		0u);					// reference
196 
197 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
198 	{
199 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
200 		DE_NULL,													// const void*								pNext;
201 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
202 		VK_FALSE,													// VkBool32									depthTestEnable;
203 		VK_FALSE,													// VkBool32									depthWriteEnable;
204 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
205 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
206 		VK_FALSE,													// VkBool32									stencilTestEnable;
207 		stencilOpStateBasic,										// VkStencilOpState							front;
208 		stencilOpStateBasic,										// VkStencilOpState							back;
209 		0.0f,														// float									minDepthBounds;
210 		1.0f,														// float									maxDepthBounds;
211 	};
212 
213 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
214 	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
215 	{
216 		VK_FALSE,							// VkBool32					blendEnable;
217 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcColorBlendFactor;
218 		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstColorBlendFactor;
219 		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
220 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcAlphaBlendFactor;
221 		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstAlphaBlendFactor;
222 		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
223 		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
224 	};
225 
226 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
227 	{
228 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
229 		DE_NULL,													// const void*									pNext;
230 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
231 		VK_FALSE,													// VkBool32										logicOpEnable;
232 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
233 		1u,															// deUint32										attachmentCount;
234 		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
235 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
236 	};
237 
238 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
239 	{
240 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
241 		DE_NULL,											// const void*										pNext;
242 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
243 		static_cast<deUint32>(m_shaderStages.size()),		// deUint32											stageCount;
244 		&m_shaderStages[0],									// const VkPipelineShaderStageCreateInfo*			pStages;
245 		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
246 		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
247 		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
248 		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
249 		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
250 		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
251 		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
252 		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
253 		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
254 		pipelineLayout,										// VkPipelineLayout									layout;
255 		renderPass,											// VkRenderPass										renderPass;
256 		0u,													// deUint32											subpass;
257 		DE_NULL,											// VkPipeline										basePipelineHandle;
258 		0,													// deInt32											basePipelineIndex;
259 	};
260 
261 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
262 }
263 
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)264 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
265 {
266 	const VkImageCreateInfo imageInfo =
267 	{
268 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
269 		DE_NULL,									// const void*              pNext;
270 		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
271 		VK_IMAGE_TYPE_2D,							// VkImageType              imageType;
272 		format,										// VkFormat                 format;
273 		makeExtent3D(size.x(), size.y(), 1),		// VkExtent3D               extent;
274 		1u,											// uint32_t                 mipLevels;
275 		1u,											// uint32_t                 arrayLayers;
276 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
277 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
278 		usage,										// VkImageUsageFlags        usage;
279 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
280 		0u,											// uint32_t                 queueFamilyIndexCount;
281 		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
282 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
283 	};
284 	return imageInfo;
285 }
286 
requireFeatures(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const FeatureFlags flags)287 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
288 {
289 	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
290 
291 	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
292 		throw tcu::NotSupportedError("Tessellation shader not supported");
293 
294 	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
295 		throw tcu::NotSupportedError("Geometry shader not supported");
296 
297 	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
298 		throw tcu::NotSupportedError("Double-precision floats not supported");
299 
300 	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
301 		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
302 
303 	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
304 		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
305 }
306 
307 } // pipeline
308 } // vkt
309