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
38namespace vkt
39{
40namespace ShaderObject
41{
42
43namespace
44{
45
46class ShaderObjectCreateInstance : public vkt::TestInstance
47{
48public:
49						ShaderObjectCreateInstance	(Context& context, const bool useMeshShaders)
50							: vkt::TestInstance	(context)
51							, m_useMeshShaders	(useMeshShaders)
52							{}
53	virtual				~ShaderObjectCreateInstance	(void) {}
54
55	tcu::TestStatus		iterate						(void) override;
56
57private:
58	const bool m_useMeshShaders;
59};
60
61tcu::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
314class ShaderObjectCreateCase : public vkt::TestCase
315{
316public:
317					ShaderObjectCreateCase	(tcu::TestContext& testCtx, const std::string& name, const bool useMeshShaders)
318						: vkt::TestCase		(testCtx, name)
319						, m_useMeshShaders	(useMeshShaders)
320						{}
321	virtual			~ShaderObjectCreateCase	(void) {}
322
323	void			checkSupport			(vkt::Context& context) const override;
324	virtual void	initPrograms			(vk::SourceCollections& programCollection) const override;
325	TestInstance*	createInstance			(Context& context) const override { return new ShaderObjectCreateInstance(context, m_useMeshShaders); }
326private:
327	bool m_useMeshShaders;
328};
329
330void ShaderObjectCreateCase::checkSupport(Context& context) const
331{
332	context.requireDeviceFunctionality("VK_EXT_shader_object");
333}
334
335void 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
453class ShaderObjectStageInstance : public vkt::TestInstance
454{
455public:
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
463	virtual				~ShaderObjectStageInstance	(void) {}
464
465	tcu::TestStatus		iterate						(void) override;
466private:
467	const vk::VkShaderStageFlagBits	m_stage;
468	const bool						m_fail;
469	const bool						m_useMeshShaders;
470};
471
472tcu::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
623class ShaderObjectStageCase : public vkt::TestCase
624{
625public:
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						{}
632	virtual			~ShaderObjectStageCase	(void) {}
633
634	void			checkSupport			(vkt::Context& context) const override;
635	virtual void	initPrograms			(vk::SourceCollections& programCollection) const override;
636	TestInstance*	createInstance			(Context& context) const override { return new ShaderObjectStageInstance(context, m_stage, m_fail, m_useMeshShaders); }
637private:
638	const vk::VkShaderStageFlagBits			m_stage;
639	const bool								m_fail;
640	const bool								m_useMeshShaders;
641};
642
643void 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
659void 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
783tcu::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