1/*-------------------------------------------------------------------------
2* Vulkan Conformance Tests
3* ------------------------
4*
5* Copyright (c) 2017 Khronos Group
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 Checks vkGetPhysicalDevice*FormatProperties* API functions
22*//*--------------------------------------------------------------------*/
23
24#include "vkDefs.hpp"
25#include "vkDeviceUtil.hpp"
26#include "vkQueryUtil.hpp"
27#include "vktTestCaseUtil.hpp"
28#include "vktApiPhysicalDeviceFormatPropertiesMaint5Tests.hpp"
29
30#include <algorithm>
31#include <array>
32
33using namespace vk;
34
35namespace vkt
36{
37namespace api
38{
39
40namespace
41{
42
43constexpr deUint32 HAS_FORMAT_PARAM	= 1u << 30;
44constexpr deUint32 HAS_FLAGS_PARAM	= 1u << 31;
45enum class FuncIDs : deUint32
46{
47	DeviceFormatProps					= 100u | HAS_FORMAT_PARAM,
48	DeviceFormatPropsSecond				= 101u | HAS_FORMAT_PARAM,
49	DeviceImageFormatProps				= 200u | HAS_FORMAT_PARAM | HAS_FLAGS_PARAM,
50	DeviceImageFormatPropsSecond		= 201u | HAS_FORMAT_PARAM | HAS_FLAGS_PARAM,
51	DeviceSparseImageFormatProps		= 300u | HAS_FORMAT_PARAM | HAS_FLAGS_PARAM,
52	DeviceSparseImageFormatPropsSecond	= 301u | HAS_FORMAT_PARAM | HAS_FLAGS_PARAM,
53};
54
55struct TestParams
56{
57	FuncIDs	funcID;
58};
59
60class UnsupportedParametersMaintenance5FormatInstance : public TestInstance
61{
62public:
63							UnsupportedParametersMaintenance5FormatInstance		(Context& context, const TestParams& params)
64								: TestInstance	(context)
65								, m_params	(params) {}
66	virtual					~UnsupportedParametersMaintenance5FormatInstance	(void) override = default;
67	virtual tcu::TestStatus	iterate												(void) override;
68protected:
69	TestParams	m_params;
70};
71
72class UnsupportedParametersMaintenance5FlagsInstance : public TestInstance
73{
74public:
75							UnsupportedParametersMaintenance5FlagsInstance	(Context& context, const TestParams& params)
76								: TestInstance	(context)
77								, m_params	(params) {}
78	virtual					~UnsupportedParametersMaintenance5FlagsInstance	(void) override = default;
79	virtual tcu::TestStatus	iterate											(void) override;
80protected:
81	TestParams	m_params;
82};
83
84class UnsupportedParametersMaintenance5TestCase : public TestCase
85{
86public:
87						UnsupportedParametersMaintenance5TestCase	(tcu::TestContext&		testContext,
88																	 const std::string&		name,
89																	 const TestParams&		params,
90																	 bool					testFormatOrFlags)
91							: TestCase				(testContext, name)
92							, m_params				(params)
93							, m_testFormatOrFlags	(testFormatOrFlags) { }
94	virtual				~UnsupportedParametersMaintenance5TestCase	(void) = default;
95	void				checkSupport								(Context&				context) const override;
96	TestInstance*		createInstance								(Context&				context) const override;
97
98protected:
99	const TestParams	m_params;
100	const bool			m_testFormatOrFlags;
101};
102
103TestInstance* UnsupportedParametersMaintenance5TestCase::createInstance (Context& context) const
104{
105	if (m_testFormatOrFlags)
106		return new UnsupportedParametersMaintenance5FormatInstance(context, m_params);
107	return new UnsupportedParametersMaintenance5FlagsInstance(context, m_params);
108}
109
110void UnsupportedParametersMaintenance5TestCase::checkSupport (Context &context) const
111{
112	context.requireDeviceFunctionality("VK_KHR_maintenance5");
113	if (context.getMaintenance5Features().maintenance5 != VK_TRUE)
114	{
115		TCU_THROW(NotSupportedError, "Maintenance5 feature is not supported by this implementation");
116	}
117}
118
119bool operator==(const VkFormatProperties& l, const VkFormatProperties& r)
120{
121	return	l.bufferFeatures		== r.bufferFeatures
122		&&	l.linearTilingFeatures	== r.linearTilingFeatures
123		&&	l.optimalTilingFeatures	== r.optimalTilingFeatures;
124}
125
126bool operator==(const VkImageFormatProperties& l, const VkImageFormatProperties& r)
127{
128	return	l.maxMipLevels		== r.maxMipLevels
129		&&	l.maxArrayLayers	== r.maxArrayLayers
130		&&	l.sampleCounts		== r.sampleCounts
131		&&	l.maxResourceSize	== r.maxResourceSize;
132}
133
134template<class StructType>
135StructType makeInvalidVulkanStructure (void* pNext = DE_NULL)
136{
137	StructType s;
138	deMemset(&s, 0xFF, (size_t)(sizeof(s)));
139	s.sType	= getStructureType<StructType>();
140	s.pNext	= pNext;
141	return s;
142}
143
144tcu::TestStatus UnsupportedParametersMaintenance5FormatInstance::iterate (void)
145{
146	const VkPhysicalDevice				dev				= m_context.getPhysicalDevice();
147	const InstanceInterface&			inst			= m_context.getInstanceInterface();
148	VkResult							res				= VK_ERROR_FORMAT_NOT_SUPPORTED;
149	uint32_t							propsCount		= 0;
150	const VkImageUsageFlags				usage			= VK_IMAGE_USAGE_STORAGE_BIT;
151	const VkImageType					imageType		= VK_IMAGE_TYPE_2D;
152	const VkImageTiling					tiling			= VK_IMAGE_TILING_OPTIMAL;
153	const VkImageCreateFlags			createFlags		= 0;
154	const VkSampleCountFlagBits			sampling		= VK_SAMPLE_COUNT_1_BIT;
155	VkFormatProperties2					props2			= initVulkanStructure();
156	VkFormatProperties&					props1			= props2.formatProperties;
157	const VkFormatProperties			invalidProps	= makeInvalidVulkanStructure<VkFormatProperties2>().formatProperties;
158	const VkFormatProperties			emptyProps		{};
159	VkImageFormatProperties2			imageProps2		= initVulkanStructure();
160	VkImageFormatProperties&			imageProps1		= imageProps2.imageFormatProperties;
161	const VkImageFormatProperties		invalidImgProps	= makeInvalidVulkanStructure<VkImageFormatProperties2>().imageFormatProperties;
162	const VkImageFormatProperties		emptyImgProps	{};
163
164	VkPhysicalDeviceImageFormatInfo2	imageFormatInfo	= initVulkanStructure();
165	imageFormatInfo.format	= VK_FORMAT_UNDEFINED;
166	imageFormatInfo.type	= imageType;
167	imageFormatInfo.tiling	= tiling;
168	imageFormatInfo.usage	= usage;
169	imageFormatInfo.flags	= createFlags;
170
171	VkPhysicalDeviceSparseImageFormatInfo2	sparseFormatInfo	= initVulkanStructure();
172	sparseFormatInfo.format		= VK_FORMAT_UNDEFINED;
173	sparseFormatInfo.type		= imageType;
174	sparseFormatInfo.samples	= sampling;
175	sparseFormatInfo.usage		= usage;
176	sparseFormatInfo.tiling		= tiling;
177
178	const deUint32						n				= 5;
179	std::array<bool, n>					verdicts;
180
181	DE_ASSERT(deUint32(m_params.funcID) & HAS_FORMAT_PARAM);
182
183	for (deUint32 i = 0; i < n; ++i)
184	{
185		const VkFormat format = VkFormat(VK_FORMAT_MAX_ENUM - i);
186
187		switch (m_params.funcID)
188		{
189		case FuncIDs::DeviceFormatProps:
190			props2 = makeInvalidVulkanStructure<VkFormatProperties2>();
191			inst.getPhysicalDeviceFormatProperties(dev, format, &props1);
192			verdicts[i] = (emptyProps == props1 || invalidProps == props1);
193			break;
194
195		case FuncIDs::DeviceFormatPropsSecond:
196			props2 = makeInvalidVulkanStructure<VkFormatProperties2>();
197			inst.getPhysicalDeviceFormatProperties2(dev, format, &props2);
198			verdicts[i] = (emptyProps == props1 || invalidProps == props1);
199			break;
200
201		case FuncIDs::DeviceImageFormatProps:
202			imageProps2 = makeInvalidVulkanStructure<VkImageFormatProperties2>();
203			res = inst.getPhysicalDeviceImageFormatProperties(dev, format, imageType, tiling, usage, createFlags, &imageProps1);
204			verdicts[i] = (emptyImgProps == imageProps1 || invalidImgProps == imageProps1);
205			break;
206
207		case FuncIDs::DeviceImageFormatPropsSecond:
208			imageProps2 = makeInvalidVulkanStructure<VkImageFormatProperties2>();
209			imageFormatInfo.format = format;
210			res = inst.getPhysicalDeviceImageFormatProperties2(dev, &imageFormatInfo, &imageProps2);
211			verdicts[i] = (emptyImgProps == imageProps1 || invalidImgProps == imageProps1);
212			break;
213
214		case FuncIDs::DeviceSparseImageFormatProps:
215			propsCount = 0;
216			inst.getPhysicalDeviceSparseImageFormatProperties(dev, format, imageType, sampling, usage, tiling, &propsCount, nullptr);
217			verdicts[i] = (0 == propsCount);
218			break;
219
220		case FuncIDs::DeviceSparseImageFormatPropsSecond:
221			propsCount = 0;
222			sparseFormatInfo.format = format;
223			inst.getPhysicalDeviceSparseImageFormatProperties2(dev, &sparseFormatInfo, &propsCount, nullptr);
224			verdicts[i] = (0 == propsCount);
225			break;
226
227		default: DE_ASSERT(0); break;
228		}
229	}
230
231	return (VK_ERROR_FORMAT_NOT_SUPPORTED == res && std::all_of(verdicts.begin(), verdicts.end(), [](bool x){ return x; }))
232			? tcu::TestStatus::pass("")
233			: tcu::TestStatus::fail("");
234}
235
236tcu::TestStatus UnsupportedParametersMaintenance5FlagsInstance::iterate (void)
237{
238	const VkPhysicalDevice				dev				= m_context.getPhysicalDevice();
239	const InstanceInterface&			inst			= m_context.getInstanceInterface();
240	VkResult							res				= VK_ERROR_FORMAT_NOT_SUPPORTED;
241	const VkFormat						format			= VK_FORMAT_R8G8B8A8_UNORM;
242	const VkImageType					imageType		= VK_IMAGE_TYPE_2D;
243	const VkImageTiling					tiling			= VK_IMAGE_TILING_OPTIMAL;
244	const VkImageCreateFlags			createFlags		= 0;
245	const VkSampleCountFlagBits			sampling		= VK_SAMPLE_COUNT_1_BIT;
246	uint32_t							propsCount		= 0;
247	VkImageFormatProperties2			imageProps2		= initVulkanStructure();
248	VkImageFormatProperties&			imageProps1		= imageProps2.imageFormatProperties;
249	const VkImageFormatProperties		invalidImgProps	= makeInvalidVulkanStructure<VkImageFormatProperties2>().imageFormatProperties;
250	const VkImageFormatProperties		emptyImgProps	{};
251
252	VkPhysicalDeviceImageFormatInfo2	imageFormatInfo	= initVulkanStructure();
253	imageFormatInfo.format	= format;
254	imageFormatInfo.type	= imageType;
255	imageFormatInfo.tiling	= tiling;
256	imageFormatInfo.usage	= VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM;
257	imageFormatInfo.flags	= createFlags;
258
259	VkPhysicalDeviceSparseImageFormatInfo2	sparseFormatInfo	= initVulkanStructure();
260	sparseFormatInfo.format		= format;
261	sparseFormatInfo.type		= imageType;
262	sparseFormatInfo.samples	= sampling;
263	sparseFormatInfo.usage		= VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM;
264	sparseFormatInfo.tiling		= tiling;
265
266	const deUint32						n				= 5;
267	std::array<bool, n>					verdicts;
268
269	DE_ASSERT(deUint32(m_params.funcID) & HAS_FLAGS_PARAM);
270
271	for (deUint32 i = 0; i < n; ++i)
272	{
273		const VkImageUsageFlags usage = VkImageUsageFlags(VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM - i);
274
275		switch (m_params.funcID)
276		{
277		case FuncIDs::DeviceImageFormatProps:
278			imageProps2 = makeInvalidVulkanStructure<VkImageFormatProperties2>();
279			res = inst.getPhysicalDeviceImageFormatProperties(dev, format, imageType, tiling, usage, createFlags, &imageProps1);
280			verdicts[i] = (emptyImgProps == imageProps1 || invalidImgProps == imageProps1);
281			break;
282
283		case FuncIDs::DeviceImageFormatPropsSecond:
284			imageProps2 = makeInvalidVulkanStructure<VkImageFormatProperties2>();
285			imageFormatInfo.usage = usage;
286			res = inst.getPhysicalDeviceImageFormatProperties2(dev, &imageFormatInfo, &imageProps2);
287			verdicts[i] = (emptyImgProps == imageProps1 || invalidImgProps == imageProps1);
288			break;
289
290		case FuncIDs::DeviceSparseImageFormatProps:
291			propsCount = 0;
292			inst.getPhysicalDeviceSparseImageFormatProperties(dev, format, imageType, sampling, usage, tiling, &propsCount, nullptr);
293			/*
294			 * Some of the Implementations ignore wrong flags, so at this point we consider the test passed.
295			 */
296			verdicts[i] = true;
297			break;
298
299		case FuncIDs::DeviceSparseImageFormatPropsSecond:
300			propsCount = 0;
301			sparseFormatInfo.usage = usage;
302			inst.getPhysicalDeviceSparseImageFormatProperties2(dev, &sparseFormatInfo, &propsCount, nullptr);
303			/*
304			 * Some of the Implementations ignore wrong formats, so at this point we consider the test passed.
305			 */
306			verdicts[i] = true;
307			break;
308
309		default: DE_ASSERT(0); break;
310		}
311	}
312
313	return (VK_ERROR_FORMAT_NOT_SUPPORTED == res && std::all_of(verdicts.begin(), verdicts.end(), [](bool x){ return x; }))
314			? tcu::TestStatus::pass("")
315			: tcu::TestStatus::fail("");
316}
317
318} // unnamed namespace
319
320tcu::TestCaseGroup*	createMaintenance5Tests	(tcu::TestContext& testCtx)
321{
322	const std::pair<std::string, FuncIDs> funcs[]
323	{
324		{ "device_format_props",		FuncIDs::DeviceFormatProps	},
325		{ "device_format_props2",		FuncIDs::DeviceFormatPropsSecond	},
326		{ "image_format_props",			FuncIDs::DeviceImageFormatProps		},
327		{ "image_format_props2",		FuncIDs::DeviceImageFormatPropsSecond	},
328		{ "sparse_image_format_props",	FuncIDs::DeviceSparseImageFormatProps	},
329		{ "sparse_image_format_props2",	FuncIDs::DeviceSparseImageFormatPropsSecond	}
330	};
331	// Checks vkGetPhysicalDevice*FormatProperties* API functions
332	de::MovePtr<tcu::TestCaseGroup> gRoot(new tcu::TestCaseGroup(testCtx, "maintenance5"));
333	de::MovePtr<tcu::TestCaseGroup> gFormat(new tcu::TestCaseGroup(testCtx, "format", ""));
334	de::MovePtr<tcu::TestCaseGroup> gFlags(new tcu::TestCaseGroup(testCtx, "flags", ""));
335	for (const auto& func : funcs)
336	{
337		TestParams p;
338		p.funcID = func.second;
339
340		if (deUint32(func.second) & HAS_FORMAT_PARAM)
341			gFormat->addChild(new UnsupportedParametersMaintenance5TestCase(testCtx, func.first, p, true));
342		if (deUint32(func.second) & HAS_FLAGS_PARAM)
343			gFlags->addChild(new UnsupportedParametersMaintenance5TestCase(testCtx, func.first, p, false));
344	}
345	gRoot->addChild(gFormat.release());
346	gRoot->addChild(gFlags.release());
347	return gRoot.release();
348}
349
350} // api
351} // vkt
352