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