• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 LunarG, Inc.
6  * Copyright (c) 2023 Nintendo
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Shader Object Create Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectCreateTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vktCustomInstancesDevices.hpp"
31 #include "tcuCommandLine.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkRefUtil.hpp"
34 #include "deRandom.hpp"
35 #include "vktShaderObjectCreateUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 
38 namespace vkt
39 {
40 namespace ShaderObject
41 {
42 
43 namespace
44 {
45 
46 class ShaderObjectCreateInstance : public vkt::TestInstance
47 {
48 public:
ShaderObjectCreateInstance(Context & context,const bool useMeshShaders)49 						ShaderObjectCreateInstance	(Context& context, const bool useMeshShaders)
50 							: vkt::TestInstance	(context)
51 							, m_useMeshShaders	(useMeshShaders)
52 							{}
~ShaderObjectCreateInstance(void)53 	virtual				~ShaderObjectCreateInstance	(void) {}
54 
55 	tcu::TestStatus		iterate						(void) override;
56 
57 private:
58 	const bool m_useMeshShaders;
59 };
60 
iterate(void)61 tcu::TestStatus ShaderObjectCreateInstance::iterate	(void)
62 {
63 	const vk::VkInstance		instance					= m_context.getInstance();
64 	const vk::InstanceDriver	instanceDriver				(m_context.getPlatformInterface(), instance);
65 	const vk::DeviceInterface&	vk							= m_context.getDeviceInterface();
66 	const vk::VkDevice			device						= m_context.getDevice();
67 	tcu::TestLog&				log							= m_context.getTestContext().getLog();
68 	const bool					tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
69 	const bool					geometrySupported			= m_context.getDeviceFeatures().geometryShader;
70 
71 	const auto&					binaries		= m_context.getBinaryCollection();
72 	const auto&					vert			= binaries.get("vert");
73 	const auto&					tesc			= binaries.get("tesc");
74 	const auto&					tese			= binaries.get("tese");
75 	const auto&					geom			= binaries.get("geom");
76 	const auto&					frag			= binaries.get("frag");
77 	const auto&					comp			= binaries.get("comp");
78 
79 	const vk::VkDescriptorSetLayoutBinding layoutBinding =
80 	{
81 		0u,														// deUint32					binding;
82 		vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,					// VkDescriptorType			descriptorType;
83 		1u,														// deUint32					arraySize;
84 		vk::VK_SHADER_STAGE_COMPUTE_BIT,						// VkShaderStageFlags		stageFlags;
85 		DE_NULL													// const VkSampler*			pImmutableSamplers;
86 	};
87 
88 	const vk::VkDescriptorSetLayoutCreateInfo descriptorLayoutParams =
89 	{
90 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType;
91 		DE_NULL,													// const void*							pNext;
92 		(vk::VkDescriptorSetLayoutCreateFlags)0,					// VkDescriptorSetLayoutCreateFlags		flags;
93 		1u,															// deUint32								count;
94 		&layoutBinding												// const VkDescriptorSetLayoutBinding	pBinding;
95 	};
96 
97 	const auto descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &descriptorLayoutParams);
98 
99 	// Todo: remove const_cast if spec is updated
100 	vk::VkDescriptorSetLayout* setLayout = const_cast<vk::VkDescriptorSetLayout*>(&descriptorSetLayout.get());
101 
102 	std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos =
103 	{
104 		{
105 			vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
106 			DE_NULL,										// const void*					pNext;
107 			0u,												// VkShaderCreateFlagsEXT		flags;
108 			vk::VK_SHADER_STAGE_VERTEX_BIT,					// VkShaderStageFlagBits		stage;
109 			vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_VERTEX_BIT, tessellationSupported, geometrySupported),	// VkShaderStageFlags			nextStage;
110 			vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
111 			vert.getSize(),									// size_t						codeSize;
112 			vert.getBinary(),								// const void*					pCode;
113 			"main",											// const char*					pName;
114 			0u,												// uint32_t						setLayoutCount;
115 			DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
116 			0u,												// uint32_t						pushConstantRangeCount;
117 			DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
118 			DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
119 		},
120 		{
121 			vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
122 			DE_NULL,										// const void*					pNext;
123 			0u,												// VkShaderCreateFlagsEXT		flags;
124 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,				// VkShaderStageFlagBits		stage;
125 			vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_FRAGMENT_BIT, tessellationSupported, geometrySupported),	// VkShaderStageFlags			nextStage;
126 			vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
127 			frag.getSize(),									// size_t						codeSize;
128 			frag.getBinary(),								// const void*					pCode;
129 			"main",											// const char*					pName;
130 			0u,												// uint32_t						setLayoutCount;
131 			DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
132 			0u,												// uint32_t						pushConstantRangeCount;
133 			DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
134 			DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
135 		},
136 		{
137 			vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
138 			DE_NULL,										// const void*					pNext;
139 			0u,												// VkShaderCreateFlagsEXT		flags;
140 			vk::VK_SHADER_STAGE_COMPUTE_BIT,				// VkShaderStageFlagBits		stage;
141 			0u,												// VkShaderStageFlags			nextStage;
142 			vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
143 			comp.getSize(),									// size_t						codeSize;
144 			comp.getBinary(),								// const void*					pCode;
145 			"main",											// const char*					pName;
146 			1u,												// uint32_t						setLayoutCount;
147 			setLayout,										// VkDescriptorSetLayout*		pSetLayouts;
148 			0u,												// uint32_t						pushConstantRangeCount;
149 			DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
150 			DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
151 		},
152 	};
153 
154 	if (m_context.getDeviceFeatures().tessellationShader)
155 	{
156 		shaderCreateInfos.push_back(
157 			{
158 				vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
159 				DE_NULL,										// const void*					pNext;
160 				0u,												// VkShaderCreateFlagsEXT		flags;
161 				vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	// VkShaderStageFlagBits		stage;
162 				vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tessellationSupported, geometrySupported),	// VkShaderStageFlags			nextStage;
163 				vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
164 				tesc.getSize(),									// size_t						codeSize;
165 				tesc.getBinary(),								// const void*					pCode;
166 				"main",											// const char*					pName;
167 				0u,												// uint32_t						setLayoutCount;
168 				DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
169 				0u,												// uint32_t						pushConstantRangeCount;
170 				DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
171 				DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
172 			}
173 		);
174 		shaderCreateInfos.push_back(
175 			{
176 				vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
177 				DE_NULL,										// const void*					pNext;
178 				0u,												// VkShaderCreateFlagsEXT		flags;
179 				vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,// VkShaderStageFlagBits		stage;
180 				vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tessellationSupported, geometrySupported),	// VkShaderStageFlags			nextStage;
181 				vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
182 				tese.getSize(),									// size_t						codeSize;
183 				tese.getBinary(),								// const void*					pCode;
184 				"main",											// const char*					pName;
185 				0u,												// uint32_t						setLayoutCount;
186 				DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
187 				0u,												// uint32_t						pushConstantRangeCount;
188 				DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
189 				DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
190 			}
191 		);
192 	}
193 
194 	if (m_context.getDeviceFeatures().geometryShader)
195 	{
196 		shaderCreateInfos.push_back(
197 			{
198 				vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
199 				DE_NULL,										// const void*					pNext;
200 				0u,												// VkShaderCreateFlagsEXT		flags;
201 				vk::VK_SHADER_STAGE_GEOMETRY_BIT,				// VkShaderStageFlagBits		stage;
202 				vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_GEOMETRY_BIT, tessellationSupported, geometrySupported),	// VkShaderStageFlags			nextStage;
203 				vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
204 				geom.getSize(),									// size_t						codeSize;
205 				geom.getBinary(),								// const void*					pCode;
206 				"main",											// const char*					pName;
207 				0u,												// uint32_t						setLayoutCount;
208 				DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
209 				0u,												// uint32_t						pushConstantRangeCount;
210 				DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
211 				DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
212 			}
213 		);
214 	}
215 
216 	if (m_useMeshShaders)
217 	{
218 		const auto& mesh = binaries.get("mesh");
219 		const auto& task = binaries.get("task");
220 		if (m_context.getMeshShaderFeaturesEXT().meshShader)
221 		{
222 			shaderCreateInfos.push_back(
223 				{
224 					vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
225 					DE_NULL,										// const void*					pNext;
226 					0u,												// VkShaderCreateFlagsEXT		flags;
227 					vk::VK_SHADER_STAGE_MESH_BIT_EXT,				// VkShaderStageFlagBits		stage;
228 					0u,												// VkShaderStageFlags			nextStage;
229 					vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
230 					mesh.getSize(),									// size_t						codeSize;
231 					mesh.getBinary(),								// const void*					pCode;
232 					"main",											// const char*					pName;
233 					0u,												// uint32_t						setLayoutCount;
234 					DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
235 					0u,												// uint32_t						pushConstantRangeCount;
236 					DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
237 					DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
238 				}
239 			);
240 		}
241 
242 		if (m_context.getMeshShaderFeaturesEXT().taskShader)
243 		{
244 			shaderCreateInfos.push_back(
245 				{
246 					vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
247 					DE_NULL,										// const void*					pNext;
248 					0u,												// VkShaderCreateFlagsEXT		flags;
249 					vk::VK_SHADER_STAGE_TASK_BIT_EXT,				// VkShaderStageFlagBits		stage;
250 					0u,												// VkShaderStageFlags			nextStage;
251 					vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
252 					task.getSize(),									// size_t						codeSize;
253 					task.getBinary(),								// const void*					pCode;
254 					"main",											// const char*					pName;
255 					0u,												// uint32_t						setLayoutCount;
256 					DE_NULL,										// VkDescriptorSetLayout*		pSetLayouts;
257 					0u,												// uint32_t						pushConstantRangeCount;
258 					DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
259 					DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
260 				}
261 			);
262 		}
263 	}
264 
265 	std::vector<vk::VkShaderEXT>	shadersSeparate		(shaderCreateInfos.size());
266 	std::vector<vk::VkShaderEXT>	shadersTogether		(shaderCreateInfos.size());
267 	for (deUint32 i = 0; i < (deUint32)shaderCreateInfos.size(); ++i)
268 	{
269 		vk.createShadersEXT(device, 1, &shaderCreateInfos[i], DE_NULL, &shadersSeparate[i]);
270 	}
271 	vk.createShadersEXT(device, (deUint32)shaderCreateInfos.size(), &shaderCreateInfos[0], DE_NULL, &shadersTogether[0]);
272 
273 	bool							match				= true;
274 	for (deUint32 i = 0; i < (deUint32)shaderCreateInfos.size(); ++i)
275 	{
276 		size_t dataSizeSeparate = 0;
277 		size_t dataSizeTogether = 0;
278 		vk.getShaderBinaryDataEXT(device, shadersSeparate[i], &dataSizeSeparate, DE_NULL);
279 		vk.getShaderBinaryDataEXT(device, shadersTogether[i], &dataSizeTogether, DE_NULL);
280 		if (dataSizeSeparate != dataSizeTogether)
281 		{
282 			log << tcu::TestLog::Message << "Data size of shader created separately is " << dataSizeSeparate << ", but data size of shader created in the same call with others is " << dataSizeTogether << tcu::TestLog::EndMessage;
283 			match = false;
284 			break;
285 		}
286 		std::vector<deUint8> dataSeparate(dataSizeSeparate);
287 		std::vector<deUint8> dataTogether(dataSizeTogether);
288 		vk.getShaderBinaryDataEXT(device, shadersSeparate[i], &dataSizeSeparate, &dataSeparate[0]);
289 		vk.getShaderBinaryDataEXT(device, shadersTogether[i], &dataSizeTogether, &dataTogether[0]);
290 		for (deUint32 j = 0; j < dataSizeSeparate; ++j)
291 		{
292 			if (dataSeparate[j] != dataTogether[j])
293 			{
294 				log << tcu::TestLog::Message << "Data of shader created separately and data of shader created in the same call with others does not match at index " << j << tcu::TestLog::EndMessage;
295 				match = false;
296 				break;
297 			}
298 		}
299 		if (!match)
300 			break;
301 	}
302 
303 	for (const auto& shader : shadersSeparate)
304 		vk.destroyShaderEXT(device, shader, DE_NULL);
305 	for (const auto& shader : shadersTogether)
306 		vk.destroyShaderEXT(device, shader, DE_NULL);
307 
308 	if (!match)
309 		return tcu::TestStatus::fail("Fail");
310 
311 	return tcu::TestStatus::pass("Pass");
312 }
313 
314 class ShaderObjectCreateCase : public vkt::TestCase
315 {
316 public:
ShaderObjectCreateCase(tcu::TestContext & testCtx,const std::string & name,const bool useMeshShaders)317 					ShaderObjectCreateCase	(tcu::TestContext& testCtx, const std::string& name, const bool useMeshShaders)
318 						: vkt::TestCase		(testCtx, name)
319 						, m_useMeshShaders	(useMeshShaders)
320 						{}
~ShaderObjectCreateCase(void)321 	virtual			~ShaderObjectCreateCase	(void) {}
322 
323 	void			checkSupport			(vkt::Context& context) const override;
324 	virtual void	initPrograms			(vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const325 	TestInstance*	createInstance			(Context& context) const override { return new ShaderObjectCreateInstance(context, m_useMeshShaders); }
326 private:
327 	bool m_useMeshShaders;
328 };
329 
checkSupport(Context & context) const330 void ShaderObjectCreateCase::checkSupport(Context& context) const
331 {
332 	context.requireDeviceFunctionality("VK_EXT_shader_object");
333 }
334 
initPrograms(vk::SourceCollections & programCollection) const335 void ShaderObjectCreateCase::initPrograms(vk::SourceCollections& programCollection) const
336 {
337 	std::stringstream vert;
338 	std::stringstream geom;
339 	std::stringstream tesc;
340 	std::stringstream tese;
341 	std::stringstream frag;
342 	std::stringstream comp;
343 	std::stringstream mesh;
344 	std::stringstream task;
345 
346 	vert
347 		<< "#version 450\n"
348 		<< "layout (location=0) in vec2 inPos;\n"
349 		<< "void main() {\n"
350 		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
351 		<< "    gl_Position = vec4(pos, 0.0f, 1.0f);\n"
352 		<< "}\n";
353 
354 	tesc
355 		<< "#version 450\n"
356 		<< "\n"
357 		<< "layout(vertices = 3) out;\n"
358 		<< "\n"
359 		<< "void main (void)\n"
360 		<< "{\n"
361 		<< "    gl_TessLevelInner[0] = 5.0;\n"
362 		<< "    gl_TessLevelInner[1] = 5.0;\n"
363 		<< "\n"
364 		<< "    gl_TessLevelOuter[0] = 5.0;\n"
365 		<< "    gl_TessLevelOuter[1] = 5.0;\n"
366 		<< "    gl_TessLevelOuter[2] = 5.0;\n"
367 		<< "    gl_TessLevelOuter[3] = 5.0;\n"
368 		<< "}\n";
369 
370 	tese
371 		<< "#version 450\n"
372 		<< "\n"
373 		<< "layout(quads) in;\n"
374 		<< "\n"
375 		<< "void main (void)\n"
376 		<< "{\n"
377 		<< "    highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
378 		<< "    highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
379 		<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
380 		<< "}\n";
381 
382 	geom
383 		<< "#version 450\n"
384 		<< "layout(points) in;\n"
385 		<< "layout(points, max_vertices = 1) out;\n"
386 		<< "\n"
387 		<< "void main(void)\n"
388 		<< "{\n"
389 		<< "    gl_Position = gl_in[0].gl_Position;\n"
390 		<< "    EmitVertex();\n"
391 		<< "    EndPrimitive();\n"
392 		<< "}\n";
393 
394 	frag
395 		<< "#version 450\n"
396 		<< "layout (location=0) out vec4 outColor;\n"
397 		<< "void main() {\n"
398 		<< "    outColor = vec4(1.0f);\n"
399 		<< "}\n";
400 
401 	comp
402 		<< "#version 450\n"
403 		<< "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
404 		<< "layout(binding = 0) buffer Output {\n"
405 		<< "    uint values[16];\n"
406 		<< "} buffer_out;\n\n"
407 		<< "void main() {\n"
408 		<< "    buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
409 		<< "}\n";
410 
411 	mesh
412 		<< "#version 460\n"
413 		<< "#extension GL_EXT_mesh_shader : require\n"
414 		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
415 		<< "layout(max_vertices = 3) out;\n"
416 		<< "layout(max_primitives = 1) out;\n"
417 		<< "layout(triangles) out;\n"
418 		<< "void main() {\n"
419 		<< "      SetMeshOutputsEXT(3,1);\n"
420 		<< "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n"
421 		<< "      gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n"
422 		<< "      gl_MeshVerticesEXT[2].gl_Position = vec4( 0.0,  1.0, 0, 1);\n"
423 		<< "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0,1,2);\n"
424 		<< "}\n";
425 
426 	task
427 		<< "#version 450\n"
428 		<< "#extension GL_EXT_mesh_shader : enable\n"
429 		<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
430 		<< "struct TaskData {\n"
431 		<< "	int t;\n"
432 		<< "};\n"
433 		<< "taskPayloadSharedEXT TaskData td;\n"
434 		<< "void main ()\n"
435 		<< "{\n"
436 		<< "	td.t = 1;\n"
437 		<< "	EmitMeshTasksEXT(1u, 1u, 1u);\n"
438 		<< "}\n";
439 
440 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
441 	programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
442 	programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
443 	programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
444 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
445 	programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
446 	if (m_useMeshShaders)
447 	{
448 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
449 		programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
450 	}
451 }
452 
453 class ShaderObjectStageInstance : public vkt::TestInstance
454 {
455 public:
ShaderObjectStageInstance(Context & context,const vk::VkShaderStageFlagBits stage,const bool fail,const bool useMeshShaders)456 						ShaderObjectStageInstance	(Context& context, const vk::VkShaderStageFlagBits stage, const bool fail, const bool useMeshShaders)
457 							: vkt::TestInstance	(context)
458 							, m_stage			(stage)
459 							, m_fail			(fail)
460 							, m_useMeshShaders	(useMeshShaders)
461 							{}
462 
~ShaderObjectStageInstance(void)463 	virtual				~ShaderObjectStageInstance	(void) {}
464 
465 	tcu::TestStatus		iterate						(void) override;
466 private:
467 	const vk::VkShaderStageFlagBits	m_stage;
468 	const bool						m_fail;
469 	const bool						m_useMeshShaders;
470 };
471 
iterate(void)472 tcu::TestStatus ShaderObjectStageInstance::iterate (void)
473 {
474 	const vk::VkInstance					instance				= m_context.getInstance();
475 	const vk::InstanceDriver				instanceDriver			(m_context.getPlatformInterface(), instance);
476 	const vk::DeviceInterface&				vk						= m_context.getDeviceInterface();
477 	const vk::VkDevice						device					= m_context.getDevice();
478 	tcu::TestLog&							log						= m_context.getTestContext().getLog();
479 	const bool								tessellationSupported	= m_context.getDeviceFeatures().tessellationShader;
480 	const bool								geometrySupported		= m_context.getDeviceFeatures().geometryShader;
481 
482 	const auto&								binaries		= m_context.getBinaryCollection();
483 
484 	de::Random								random			(102030);
485 	std::vector<vk::VkShaderStageFlagBits>	stages			=
486 	{
487 		vk::VK_SHADER_STAGE_VERTEX_BIT,
488 		vk::VK_SHADER_STAGE_FRAGMENT_BIT,
489 		vk::VK_SHADER_STAGE_COMPUTE_BIT,
490 	};
491 	if (m_context.getDeviceFeatures().tessellationShader)
492 	{
493 		stages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
494 		stages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
495 	}
496 	if (m_context.getDeviceFeatures().geometryShader)
497 	{
498 		stages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT);
499 	}
500 	if (m_useMeshShaders)
501 	{
502 		if (m_context.getMeshShaderFeaturesEXT().meshShader)
503 			stages.push_back(vk::VK_SHADER_STAGE_MESH_BIT_EXT);
504 		if (m_context.getMeshShaderFeaturesEXT().taskShader)
505 			stages.push_back(vk::VK_SHADER_STAGE_TASK_BIT_EXT);
506 	}
507 
508 	const deUint32								count	= m_stage == vk::VK_SHADER_STAGE_ALL ? 50 : 10;
509 
510 	const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
511 		vk::DescriptorSetLayoutBuilder()
512 		.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
513 		.build(vk, device));
514 
515 
516 	std::vector<vk::VkShaderCreateInfoEXT>		shaderCreateInfos;
517 
518 	for (deUint32 i = 0; i < count; ++i)
519 	{
520 		vk::VkShaderStageFlagBits stage;
521 		if (m_stage == vk::VK_SHADER_STAGE_ALL)
522 			stage = stages[random.getUint32() % stages.size()];
523 		else
524 			stage = m_stage;
525 
526 		bool useLayout = stage == vk::VK_SHADER_STAGE_COMPUTE_BIT;
527 
528 		const auto&				src			= binaries.get(getShaderName(stage) + std::to_string(i % 10));
529 		shaderCreateInfos.push_back(
530 			{
531 				vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,	// VkStructureType				sType;
532 				DE_NULL,										// const void*					pNext;
533 				0u,												// VkShaderCreateFlagsEXT		flags;
534 				stage,											// VkShaderStageFlagBits		stage;
535 				vk::getShaderObjectNextStages(stage, tessellationSupported, geometrySupported),			// VkShaderStageFlags			nextStage;
536 				vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,				// VkShaderCodeTypeEXT			codeType;
537 				src.getSize(),									// size_t						codeSize;
538 				src.getBinary(),								// const void*					pCode;
539 				"main",											// const char*					pName;
540 				useLayout ? 1u : 0u,							// uint32_t						setLayoutCount;
541 				useLayout ? &*descriptorSetLayout : DE_NULL,	// VkDescriptorSetLayout*		pSetLayouts;
542 				0u,												// uint32_t						pushConstantRangeCount;
543 				DE_NULL,										// const VkPushConstantRange*	pPushConstantRanges;
544 				DE_NULL,										// const VkSpecializationInfo*	pSpecializationInfo;
545 			});
546 	}
547 
548 	std::vector<vk::VkShaderEXT>		shaders			(count, VK_NULL_HANDLE);
549 	vk::VkResult						result;
550 	result = vk.createShadersEXT(device, count, &shaderCreateInfos[0], DE_NULL, &shaders[0]);
551 	if (result != vk::VK_SUCCESS)
552 	{
553 		log << tcu::TestLog::Message << "vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage;
554 		return tcu::TestStatus::fail("Fail");
555 	}
556 
557 	std::vector<size_t>					binarySizes		(count);
558 	std::vector<std::vector<deUint8>>	binaryData		(count);
559 	for (size_t i = 0; i < count; ++i)
560 	{
561 		vk.getShaderBinaryDataEXT(device, shaders[i], &binarySizes[i], DE_NULL);
562 		binaryData[i].resize(binarySizes[i]);
563 		vk.getShaderBinaryDataEXT(device, shaders[i], &binarySizes[i], (void*)&binaryData[i][0]);
564 	}
565 
566 	for (const auto& shader : shaders)
567 		vk.destroyShaderEXT(device, shader, DE_NULL);
568 
569 	const deUint32	failIndex = random.getUint32() % count;
570 
571 	for (deUint32 i = 0; i < count; ++i)
572 	{
573 		shaderCreateInfos[i].codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
574 		if (m_fail && failIndex == i)
575 			shaderCreateInfos[i].codeSize = 1;
576 		else
577 			shaderCreateInfos[i].codeSize = binarySizes[i];
578 		shaderCreateInfos[i].pCode = &binaryData[i][0];
579 	}
580 
581 	deUint32 garbage = 1234u;
582 	std::vector<vk::VkShaderEXT>		binaryShaders	(count, garbage); // Fill with garbage
583 	result = vk.createShadersEXT(device, count, &shaderCreateInfos[0], DE_NULL, &binaryShaders[0]);
584 
585 	if (m_fail)
586 	{
587 		if (result != vk::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)
588 		{
589 			log << tcu::TestLog::Message << "Shader at index " << failIndex << "was created with size 0, but vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage;
590 			return tcu::TestStatus::fail("Fail");
591 		}
592 
593 		for (deUint32 i = 0; i < failIndex; ++i)
594 		{
595 			if (binaryShaders[i] == garbage)
596 			{
597 				log << tcu::TestLog::Message << "vkCreateShadersEXT returned VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT and failed at index " << failIndex << ", but shader at index " << i << "was not created" << tcu::TestLog::EndMessage;
598 				return tcu::TestStatus::fail("Fail");
599 			}
600 			vk.destroyShaderEXT(device, binaryShaders[i], DE_NULL);
601 		}
602 		if (binaryShaders[failIndex] != VK_NULL_HANDLE)
603 		{
604 			log << tcu::TestLog::Message << "vkCreateShadersEXT returned VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT, creating shader at index " << failIndex << " failed, but the shader is not VK_NULL_HANDLE" << tcu::TestLog::EndMessage;
605 			return tcu::TestStatus::fail("Fail");
606 		}
607 	}
608 	else
609 	{
610 		if (result != vk::VK_SUCCESS)
611 		{
612 			log << tcu::TestLog::Message << "vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage;
613 			return tcu::TestStatus::fail("Fail");
614 		}
615 
616 		for (const auto& shader : binaryShaders)
617 			vk.destroyShaderEXT(device, shader, DE_NULL);
618 	}
619 
620 	return tcu::TestStatus::pass("Pass");
621 }
622 
623 class ShaderObjectStageCase : public vkt::TestCase
624 {
625 public:
ShaderObjectStageCase(tcu::TestContext & testCtx,const std::string & name,const vk::VkShaderStageFlagBits stage,const bool fail,const bool useMeshShaders)626 					ShaderObjectStageCase	(tcu::TestContext& testCtx, const std::string& name, const vk::VkShaderStageFlagBits stage, const bool fail, const bool useMeshShaders)
627 						: vkt::TestCase		(testCtx, name)
628 						, m_stage			(stage)
629 						, m_fail			(fail)
630 						, m_useMeshShaders	(useMeshShaders)
631 						{}
~ShaderObjectStageCase(void)632 	virtual			~ShaderObjectStageCase	(void) {}
633 
634 	void			checkSupport			(vkt::Context& context) const override;
635 	virtual void	initPrograms			(vk::SourceCollections& programCollection) const override;
createInstance(Context & context) const636 	TestInstance*	createInstance			(Context& context) const override { return new ShaderObjectStageInstance(context, m_stage, m_fail, m_useMeshShaders); }
637 private:
638 	const vk::VkShaderStageFlagBits			m_stage;
639 	const bool								m_fail;
640 	const bool								m_useMeshShaders;
641 };
642 
checkSupport(Context & context) const643 void ShaderObjectStageCase::checkSupport (Context& context) const
644 {
645 	context.requireDeviceFunctionality("VK_EXT_shader_object");
646 	if (m_useMeshShaders)
647 		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
648 
649 	if (m_stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
650 		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
651 	if (m_stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
652 		context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
653 	if (m_stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT && context.getMeshShaderFeaturesEXT().taskShader == VK_FALSE)
654 		TCU_THROW(NotSupportedError, "Task shaders not supported");
655 	if (m_stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT && context.getMeshShaderFeaturesEXT().meshShader == VK_FALSE)
656 		TCU_THROW(NotSupportedError, "Mesh shaders not supported");
657 }
658 
initPrograms(vk::SourceCollections & programCollection) const659 void ShaderObjectStageCase::initPrograms (vk::SourceCollections& programCollection) const
660 {
661 	for (deUint32 i = 0; i < 10; ++i)
662 	{
663 		std::stringstream vert;
664 		std::stringstream geom;
665 		std::stringstream tesc;
666 		std::stringstream tese;
667 		std::stringstream frag;
668 		std::stringstream comp;
669 		std::stringstream mesh;
670 		std::stringstream task;
671 
672 		vert
673 			<< "#version 450\n"
674 			<< "layout (location=0) in vec2 inPos;\n"
675 			<< "void main() {\n"
676 			<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
677 			<< "    gl_Position = vec4(pos * float(" << i << "), 0.0f, 1.0f);\n"
678 			<< "}\n";
679 
680 		tesc
681 			<< "#version 450\n"
682 			<< "\n"
683 			<< "layout(vertices = 3) out;\n"
684 			<< "\n"
685 			<< "void main (void)\n"
686 			<< "{\n"
687 			<< "    gl_TessLevelInner[0] = 5.0 + float(" << i << ");\n"
688 			<< "    gl_TessLevelInner[1] = 5.0 + float(" << i << ");\n"
689 			<< "\n"
690 			<< "    gl_TessLevelOuter[0] = 5.0;\n"
691 			<< "    gl_TessLevelOuter[1] = 5.0;\n"
692 			<< "    gl_TessLevelOuter[2] = 5.0;\n"
693 			<< "    gl_TessLevelOuter[3] = 5.0;\n"
694 			<< "}\n";
695 
696 		tese
697 			<< "#version 450\n"
698 			<< "\n"
699 			<< "layout(quads) in;\n"
700 			<< "\n"
701 			<< "void main (void)\n"
702 			<< "{\n"
703 			<< "    highp float x = gl_TessCoord.x * float(" << i << ") - 1.0;\n"
704 			<< "    highp float y = gl_TessCoord.y * float(" << i << ") - 1.0;\n"
705 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
706 			<< "}\n";
707 
708 		geom
709 			<< "#version 450\n"
710 			<< "layout(points) in;\n"
711 			<< "layout(points, max_vertices = 1) out;\n"
712 			<< "\n"
713 			<< "void main(void)\n"
714 			<< "{\n"
715 			<< "    gl_Position = gl_in[0].gl_Position;\n"
716 			<< "    gl_Position.xy += vec2(float(" << i << "));\n"
717 			<< "    EmitVertex();\n"
718 			<< "    EndPrimitive();\n"
719 			<< "}\n";
720 
721 		frag
722 			<< "#version 450\n"
723 			<< "layout (location=0) out vec4 outColor;\n"
724 			<< "void main() {\n"
725 			<< "    outColor = vec4(1.0f / (1.0f + float(" << i << ")));\n"
726 			<< "}\n";
727 
728 		comp
729 			<< "#version 450\n"
730 			<< "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
731 			<< "layout(binding = 0) buffer Output {\n"
732 			<< "    uint values[16];\n"
733 			<< "} buffer_out;\n\n"
734 			<< "void main() {\n"
735 			<< "    buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x + " << i << ";\n"
736 			<< "}\n";
737 
738 		mesh
739 			<< "#version 460\n"
740 			<< "#extension GL_EXT_mesh_shader : require\n"
741 			<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
742 			<< "layout(max_vertices = 3) out;\n"
743 			<< "layout(max_primitives = 1) out;\n"
744 			<< "layout(triangles) out;\n"
745 			<< "void main() {\n"
746 			<< "      SetMeshOutputsEXT(3,1);\n"
747 			<< "      gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n"
748 			<< "      gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n"
749 			<< "      gl_MeshVerticesEXT[2].gl_Position = vec4( 0.0,  1.0, 0, 1);\n"
750 			<< "      gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0,1,2);\n"
751 			<< "}\n";
752 
753 		task
754 			<< "#version 450\n"
755 			<< "#extension GL_EXT_mesh_shader : enable\n"
756 			<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
757 			<< "struct TaskData {\n"
758 			<< "	int t;\n"
759 			<< "};\n"
760 			<< "taskPayloadSharedEXT TaskData td;\n"
761 			<< "void main ()\n"
762 			<< "{\n"
763 			<< "	td.t = 1;\n"
764 			<< "	EmitMeshTasksEXT(1u, 1u, 1u);\n"
765 			<< "}\n";
766 
767 		programCollection.glslSources.add("vert" + std::to_string(i)) << glu::VertexSource(vert.str());
768 		programCollection.glslSources.add("tesc" + std::to_string(i)) << glu::TessellationControlSource(tesc.str());
769 		programCollection.glslSources.add("tese" + std::to_string(i)) << glu::TessellationEvaluationSource(tese.str());
770 		programCollection.glslSources.add("geom" + std::to_string(i)) << glu::GeometrySource(geom.str());
771 		programCollection.glslSources.add("frag" + std::to_string(i)) << glu::FragmentSource(frag.str());
772 		programCollection.glslSources.add("comp" + std::to_string(i)) << glu::ComputeSource(comp.str());
773 		if (m_useMeshShaders)
774 		{
775 			programCollection.glslSources.add("mesh" + std::to_string(i)) << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
776 			programCollection.glslSources.add("task" + std::to_string(i)) << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
777 		}
778 	}
779 }
780 
781 }
782 
createShaderObjectCreateTests(tcu::TestContext & testCtx)783 tcu::TestCaseGroup* createShaderObjectCreateTests (tcu::TestContext& testCtx)
784 {
785 	de::MovePtr<tcu::TestCaseGroup> createGroup(new tcu::TestCaseGroup(testCtx, "create"));
786 
787 	de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(testCtx, "multiple"));
788 
789 	multipleGroup->addChild(new ShaderObjectCreateCase(testCtx, "all", false));
790 	multipleGroup->addChild(new ShaderObjectCreateCase(testCtx, "all_with_mesh", true));
791 
792 	createGroup->addChild(multipleGroup.release());
793 
794 	const struct
795 	{
796 		vk::VkShaderStageFlagBits	stage;
797 		const bool					useMeshShaders;
798 		const char*					name;
799 	} stageTests[] =
800 	{
801 		{ vk::VK_SHADER_STAGE_VERTEX_BIT,					false,		"vert"				},
802 		{ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		false,		"tesc"				},
803 		{ vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	false,		"tese"				},
804 		{ vk::VK_SHADER_STAGE_GEOMETRY_BIT,					false,		"geom"				},
805 		{ vk::VK_SHADER_STAGE_FRAGMENT_BIT,					false,		"frag"				},
806 		{ vk::VK_SHADER_STAGE_COMPUTE_BIT,					false,		"comp"				},
807 		{ vk::VK_SHADER_STAGE_MESH_BIT_EXT,					true,		"mesh"				},
808 		{ vk::VK_SHADER_STAGE_TASK_BIT_EXT,					true,		"task"				},
809 		{ vk::VK_SHADER_STAGE_ALL,							false,		"all"				},
810 		{ vk::VK_SHADER_STAGE_ALL,							true,		"all_with_mesh"		},
811 	};
812 
813 	const struct
814 	{
815 		bool		fail;
816 		const char* name;
817 	} failTests[] =
818 	{
819 		{ false,	"succeed"		},
820 		{ true,		"fail"			},
821 	};
822 
823 	for (const auto& stage : stageTests)
824 	{
825 		de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name));
826 		for (const auto& failTest : failTests)
827 		{
828 			stageGroup->addChild(new ShaderObjectStageCase(testCtx, failTest.name, stage.stage, failTest.fail, stage.useMeshShaders));
829 		}
830 		createGroup->addChild(stageGroup.release());
831 	}
832 
833 	return createGroup.release();
834 }
835 
836 } // ShaderObject
837 } // vkt
838