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 API Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "tcuDefs.hpp"
26#include "tcuTestCase.hpp"
27#include "deUniquePtr.hpp"
28#include "tcuTestCase.hpp"
29#include "vktTestCase.hpp"
30#include "vkQueryUtil.hpp"
31#include "vktCustomInstancesDevices.hpp"
32#include "tcuCommandLine.hpp"
33
34namespace vkt
35{
36namespace ShaderObject
37{
38
39namespace
40{
41
42enum ShaderObjectApiTest {
43	EXT_DISCARD_RECTANGLES = 0,
44	NV_SCISSOR_EXCLUSIVE,
45	KHR_DYNAMIC_RENDERING,
46	SHADER_BINARY_UUID,
47};
48
49class ShaderObjectApiInstance : public vkt::TestInstance
50{
51public:
52						ShaderObjectApiInstance		(Context& context)
53							: vkt::TestInstance (context)
54							{}
55	virtual				~ShaderObjectApiInstance	(void) {}
56
57	tcu::TestStatus		iterate						(void) override;
58};
59
60tcu::TestStatus ShaderObjectApiInstance::iterate (void)
61{
62	const vk::InstanceInterface&			vki				= m_context.getInstanceInterface();
63	const vk::PlatformInterface&			vkp				= m_context.getPlatformInterface();
64	const auto								instance		= m_context.getInstance();
65	const auto								physicalDevice	= m_context.getPhysicalDevice();
66	vk::VkPhysicalDeviceFeatures2			deviceFeatures	= vk::initVulkanStructure();
67
68	vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
69
70	const auto								queuePriority	= 1.0f;
71	const vk::VkDeviceQueueCreateInfo		queueInfo
72	{
73		vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,		//	VkStructureType					sType;
74		nullptr,											//	const void*						pNext;
75		0u,													//	VkDeviceQueueCreateFlags		flags;
76		m_context.getUniversalQueueFamilyIndex(),			//	deUint32						queueFamilyIndex;
77		1u,													//	deUint32						queueCount;
78		&queuePriority,										//	const float*					pQueuePriorities;
79	};
80
81	std::vector<const char*>				extensions		= { "VK_EXT_shader_object" };
82
83	vk::VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeaturesEXT	= vk::initVulkanStructure();
84	vk::VkPhysicalDeviceFeatures2				features2				= vk::initVulkanStructure(&shaderObjectFeaturesEXT);
85	vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
86
87	const vk::VkDeviceCreateInfo			deviceInfo
88	{
89		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,			//	VkStructureType					sType;
90		&features2,											//	const void*						pNext;
91		0u,													//	VkDeviceCreateFlags				flags;
92		1u,													//	deUint32						queueCreateInfoCount;
93		&queueInfo,											//	const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
94		0u,													//	deUint32						enabledLayerCount;
95		nullptr,											//	const char* const*				ppEnabledLayerNames;
96		(deUint32)extensions.size(),						//	deUint32						enabledExtensionCount;
97		extensions.data(),									//	const char* const*				ppEnabledExtensionNames;
98		DE_NULL,											//	const VkPhysicalDeviceFeatures*	pEnabledFeatures;
99	};
100
101	const auto								device			= createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceInfo);
102
103	de::MovePtr<vk::DeviceDriver>			vkd				(new vk::DeviceDriver(vkp, instance, device.get(), m_context.getUsedApiVersion()));
104	const auto&								vk				= *vkd.get();
105
106	const std::vector<std::string> functions = {
107		// VK_EXT_extended_dynamic_state
108		"vkCmdBindVertexBuffers2EXT",
109		"vkCmdSetCullModeEXT",
110		"vkCmdSetDepthBoundsTestEnableEXT",
111		"vkCmdSetDepthCompareOpEXT",
112		"vkCmdSetDepthTestEnableEXT",
113		"vkCmdSetDepthWriteEnableEXT",
114		"vkCmdSetFrontFaceEXT",
115		"vkCmdSetPrimitiveTopologyEXT",
116		"vkCmdSetScissorWithCountEXT",
117		"vkCmdSetStencilOpEXT",
118		"vkCmdSetStencilTestEnableEXT",
119		"vkCmdSetViewportWithCountEXT",
120		// VK_EXT_extended_dynamic_state2
121		"vkCmdSetDepthBiasEnableEXT",
122		"vkCmdSetLogicOpEXT",
123		"vkCmdSetPatchControlPointsEXT",
124		"vkCmdSetPrimitiveRestartEnableEXT",
125		"vkCmdSetRasterizerDiscardEnableEXT",
126		// VK_EXT_extended_dynamic_state3
127		"vkCmdSetAlphaToCoverageEnableEXT",
128		"vkCmdSetAlphaToOneEnableEXT",
129		"vkCmdSetColorBlendAdvancedEXT",
130		"vkCmdSetColorBlendEnableEXT",
131		"vkCmdSetColorBlendEquationEXT",
132		"vkCmdSetColorWriteMaskEXT",
133		"vkCmdSetConservativeRasterizationModeEXT",
134		"vkCmdSetCoverageModulationModeNV",
135		"vkCmdSetCoverageModulationTableEnableNV",
136		"vkCmdSetCoverageModulationTableNV",
137		"vkCmdSetCoverageReductionModeNV",
138		"vkCmdSetCoverageToColorEnableNV",
139		"vkCmdSetCoverageToColorLocationNV",
140		"vkCmdSetDepthClampEnableEXT",
141		"vkCmdSetDepthClipEnableEXT",
142		"vkCmdSetDepthClipNegativeOneToOneEXT",
143		"vkCmdSetExtraPrimitiveOverestimationSizeEXT",
144		"vkCmdSetLineRasterizationModeEXT",
145		"vkCmdSetLineStippleEnableEXT",
146		"vkCmdSetLogicOpEnableEXT",
147		"vkCmdSetPolygonModeEXT",
148		"vkCmdSetProvokingVertexModeEXT",
149		"vkCmdSetRasterizationSamplesEXT",
150		"vkCmdSetRasterizationStreamEXT",
151		"vkCmdSetRepresentativeFragmentTestEnableNV",
152		"vkCmdSetSampleLocationsEnableEXT",
153		"vkCmdSetSampleMaskEXT",
154		"vkCmdSetShadingRateImageEnableNV",
155		"vkCmdSetTessellationDomainOriginEXT",
156		"vkCmdSetViewportSwizzleNV",
157		"vkCmdSetViewportWScalingEnableNV",
158		// VK_EXT_vertex_input_dynamic_state
159		"vkCmdSetVertexInputEXT",
160	};
161
162	for (const auto& func : functions)
163	{
164		const auto& f = vk.getDeviceProcAddr(*device, func.c_str());
165		if (f == DE_NULL)
166			return tcu::TestStatus::fail("Failed: " + func);
167	}
168
169	return tcu::TestStatus::pass("Pass");
170}
171
172class ShaderObjectApiCase : public vkt::TestCase
173{
174public:
175					ShaderObjectApiCase		(tcu::TestContext& testCtx, const std::string& name)
176						: vkt::TestCase		(testCtx, name)
177						{}
178	virtual			~ShaderObjectApiCase	(void) {}
179
180	void			checkSupport			(vkt::Context& context) const override;
181	TestInstance*	createInstance			(Context& context) const override { return new ShaderObjectApiInstance(context); }
182};
183
184void ShaderObjectApiCase::checkSupport (Context& context) const
185{
186	context.requireDeviceFunctionality("VK_EXT_shader_object");
187}
188
189class ShaderObjectExtensionVersionInstance : public vkt::TestInstance
190{
191public:
192						ShaderObjectExtensionVersionInstance	(Context& context, const ShaderObjectApiTest test)
193							: vkt::TestInstance	(context)
194							, m_test			(test)
195							{}
196	virtual				~ShaderObjectExtensionVersionInstance	(void) {}
197
198	tcu::TestStatus		iterate									(void) override;
199private:
200	ShaderObjectApiTest m_test;
201};
202
203tcu::TestStatus ShaderObjectExtensionVersionInstance::iterate (void)
204{
205	vk::VkInstance									instance		= m_context.getInstance();
206	vk::InstanceDriver								instanceDriver	(m_context.getPlatformInterface(), instance);
207	vk::VkPhysicalDevice							physicalDevice  = m_context.getPhysicalDevice();
208	const vk::InstanceInterface&					vki				= m_context.getInstanceInterface();
209	const vk::ApiVersion							deviceVersion	= vk::unpackVersion(m_context.getDeviceVersion());
210	tcu::TestLog&									log				= m_context.getTestContext().getLog();
211
212	vk::VkPhysicalDeviceShaderObjectPropertiesEXT	shaderObjectProperties = vk::initVulkanStructure();
213
214	vk::VkPhysicalDeviceProperties					properties;
215	deMemset(&properties, 0, sizeof(vk::VkPhysicalDeviceProperties));
216	vk::VkPhysicalDeviceProperties2					properties2 =
217	{
218		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,			// VkStructureType					sType
219		&shaderObjectProperties,									// const void*						pNext
220		properties													// VkPhysicalDeviceProperties		properties
221	};
222
223	instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &properties2);
224
225	const std::vector<vk::VkExtensionProperties>&				deviceExtensionProperties = enumerateCachedDeviceExtensionProperties(vki, physicalDevice);
226
227	if (m_test == SHADER_BINARY_UUID)
228	{
229		bool nonZero = false;
230		for (deUint32 i = 0; i < VK_UUID_SIZE; ++i)
231		{
232			if (shaderObjectProperties.shaderBinaryUUID[i] != 0)
233			{
234				nonZero = true;
235				break;
236			}
237		}
238		if (!nonZero)
239		{
240			log << tcu::TestLog::Message << "All shaderBinaryUUID bytes are 0" << tcu::TestLog::EndMessage;
241			return tcu::TestStatus::fail("Fail");
242		}
243	}
244	else if (m_test == KHR_DYNAMIC_RENDERING)
245	{
246		if (deviceVersion.majorNum == 1 && deviceVersion.minorNum < 3)
247		{
248			bool found = false;
249			for (const auto& ext : deviceExtensionProperties)
250			{
251				if (strcmp(ext.extensionName, "VK_KHR_dynamic_rendering") == 0)
252				{
253					found = true;
254					break;
255				}
256			}
257			if (!found)
258			{
259				log << tcu::TestLog::Message << "VK_EXT_shader_object is supported, but vulkan version is < 1.3 and VK_KHR_dynamic_rendering is not supported" << tcu::TestLog::EndMessage;
260				return tcu::TestStatus::fail("Fail");
261			}
262		}
263	}
264	else
265	{
266		for (const auto& ext : deviceExtensionProperties)
267		{
268			if (m_test == EXT_DISCARD_RECTANGLES)
269			{
270				if (strcmp(ext.extensionName, "VK_EXT_discard_rectangles") == 0)
271				{
272					if (ext.specVersion < 2)
273					{
274						log << tcu::TestLog::Message << "VK_EXT_shader_object and VK_EXT_discard_rectangles are supported, but VK_EXT_discard_rectangles reports version " << ext.specVersion << tcu::TestLog::EndMessage;
275						return tcu::TestStatus::fail("Fail");
276					}
277					break;
278				}
279			}
280			else if (m_test == NV_SCISSOR_EXCLUSIVE)
281			{
282				if (strcmp(ext.extensionName, "VK_NV_scissor_exclusive") == 0)
283				{
284					if (ext.specVersion < 2)
285					{
286						log << tcu::TestLog::Message << "VK_EXT_shader_object and VK_NV_scissor_exclusive are supported, but VK_NV_scissor_exclusive reports version " << ext.specVersion << tcu::TestLog::EndMessage;
287						return tcu::TestStatus::fail("Fail");
288					}
289					break;
290				}
291			}
292		}
293	}
294	return tcu::TestStatus::pass("Pass");
295}
296
297class ShaderObjectExtensionVersionCase : public vkt::TestCase
298{
299public:
300					ShaderObjectExtensionVersionCase	(tcu::TestContext& testCtx, const std::string& name, const ShaderObjectApiTest test)
301						: vkt::TestCase					(testCtx, name)
302						, m_test						(test)
303						{}
304	virtual			~ShaderObjectExtensionVersionCase	(void) {}
305
306	void			checkSupport						(vkt::Context& context) const override;
307	TestInstance*	createInstance						(Context& context) const override { return new ShaderObjectExtensionVersionInstance(context, m_test); }
308private:
309	ShaderObjectApiTest m_test;
310};
311
312void ShaderObjectExtensionVersionCase::checkSupport(Context& context) const
313{
314	context.requireDeviceFunctionality("VK_EXT_shader_object");
315	if (m_test == EXT_DISCARD_RECTANGLES)
316	{
317		context.requireDeviceFunctionality("VK_EXT_discard_rectangles");
318	}
319	else if (m_test == NV_SCISSOR_EXCLUSIVE)
320	{
321		context.requireDeviceFunctionality("VK_NV_scissor_exclusive");
322	}
323}
324}
325
326tcu::TestCaseGroup* createShaderObjectApiTests (tcu::TestContext& testCtx)
327{
328	de::MovePtr<tcu::TestCaseGroup> apiGroup(new tcu::TestCaseGroup(testCtx, "api"));
329	apiGroup->addChild(new ShaderObjectApiCase(testCtx, "get_device_proc_addr"));
330
331	const struct
332	{
333		ShaderObjectApiTest		test;
334		const char*				name;
335	} apiTests[] =
336	{
337		{ EXT_DISCARD_RECTANGLES,	"discard_rectangles"	},
338		{ NV_SCISSOR_EXCLUSIVE,		"scissor_exclusive"		},
339		{ KHR_DYNAMIC_RENDERING,	"dynamic_rendering"		},
340		{ SHADER_BINARY_UUID,		"shader_binary_uuid"	},
341	};
342
343	for (const auto& test : apiTests)
344	{
345		apiGroup->addChild(new ShaderObjectExtensionVersionCase(testCtx, test.name, test.test));
346	}
347	return apiGroup.release();
348}
349
350} // ShaderObject
351} // vkt
352