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 Binary Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectBinaryTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktShaderObjectCreateUtil.hpp"
30 #include "vktCustomInstancesDevices.hpp"
31 #include "tcuTestLog.hpp"
32 #include "deRandom.hpp"
33 #include "tcuCommandLine.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 
37 #include <cmath>
38 
39 namespace vkt
40 {
41 namespace ShaderObject
42 {
43 
44 namespace
45 {
46 
47 enum QueryType
48 {
49     SAME_SHADER,
50     NEW_SHADER,
51     SHADER_FROM_BINARY,
52     NEW_DEVICE,
53     DEVICE_NO_EXTS_FEATURES,
54     ALL_FEATURE_COMBINATIONS,
55 };
56 
57 struct TestParams
58 {
59     vk::VkShaderStageFlagBits stage;
60     bool linked;
61     QueryType queryType;
62 };
63 
64 enum IncompleteBinaryTestType
65 {
66     HALF_DATA_SIZE,
67     GARBAGE_DATA,
68     GARBAGE_SECOND_HALF,
69     CREATE_FROM_HALF_SIZE,
70     CREATE_FROM_HALF_SIZE_GARBAGE,
71 };
72 
getNextStage(vk::VkShaderStageFlagBits shaderStage,bool tessellationShaderFeature,bool geometryShaderFeature)73 vk::VkShaderStageFlags getNextStage(vk::VkShaderStageFlagBits shaderStage, bool tessellationShaderFeature,
74                                     bool geometryShaderFeature)
75 {
76     if (shaderStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
77     {
78         if (tessellationShaderFeature)
79             return vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
80         else if (geometryShaderFeature)
81             return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
82         return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
83     }
84     else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
85     {
86         return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
87     }
88     else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
89     {
90         if (geometryShaderFeature)
91             return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
92         return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
93     }
94     else if (shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
95     {
96         return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
97     }
98     return 0u;
99 }
100 
createShader(const vk::DeviceInterface & vk,const vk::BinaryCollection & binaries,const vk::VkDevice device,vk::VkPhysicalDeviceFeatures features,vk::VkDescriptorSetLayout descriptorSetLayout,bool linked,vk::VkShaderStageFlagBits stage)101 vk::Move<vk::VkShaderEXT> createShader(const vk::DeviceInterface &vk, const vk::BinaryCollection &binaries,
102                                        const vk::VkDevice device, vk::VkPhysicalDeviceFeatures features,
103                                        vk::VkDescriptorSetLayout descriptorSetLayout, bool linked,
104                                        vk::VkShaderStageFlagBits stage)
105 {
106     vk::VkShaderEXT shader;
107 
108     if (!linked)
109     {
110         const auto &src                                  = binaries.get(vk::getShaderName(stage));
111         const vk::VkShaderCreateInfoEXT shaderCreateInfo = {
112             vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
113             DE_NULL,                                      // const void* pNext;
114             0u,                                           // VkShaderCreateFlagsEXT flags;
115             stage,                                        // VkShaderStageFlagBits stage;
116             getNextStage(stage, features.tessellationShader,
117                          features.geometryShader),             // VkShaderStageFlags nextStage;
118             vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,                 // VkShaderCodeTypeEXT codeType;
119             src.getSize(),                                     // size_t codeSize;
120             src.getBinary(),                                   // const void* pCode;
121             "main",                                            // const char* pName;
122             (descriptorSetLayout != VK_NULL_HANDLE) ? 1u : 0u, // uint32_t setLayoutCount;
123             (descriptorSetLayout != VK_NULL_HANDLE) ? &descriptorSetLayout :
124                                                       DE_NULL, // VkDescriptorSetLayout* pSetLayouts;
125             0u,                                                // uint32_t pushConstantRangeCount;
126             DE_NULL,                                           // const VkPushConstantRange* pPushConstantRanges;
127             DE_NULL,                                           // const VkSpecializationInfo* pSpecializationInfo;
128         };
129 
130         vk.createShadersEXT(device, 1u, &shaderCreateInfo, DE_NULL, &shader);
131     }
132     else
133     {
134         const auto &vert = binaries.get("vert");
135         const auto &tesc = binaries.get("tesc");
136         const auto &tese = binaries.get("tese");
137         const auto &geom = binaries.get("geom");
138         const auto &frag = binaries.get("frag");
139 
140         std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos = {
141             {
142                 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
143                 DE_NULL,                                      // const void* pNext;
144                 vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,      // VkShaderCreateFlagsEXT flags;
145                 vk::VK_SHADER_STAGE_VERTEX_BIT,               // VkShaderStageFlagBits stage;
146                 getNextStage(vk::VK_SHADER_STAGE_VERTEX_BIT, features.tessellationShader,
147                              features.geometryShader), // VkShaderStageFlags nextStage;
148                 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,     // VkShaderCodeTypeEXT codeType;
149                 vert.getSize(),                        // size_t codeSize;
150                 vert.getBinary(),                      // const void* pCode;
151                 "main",                                // const char* pName;
152                 0u,                                    // uint32_t setLayoutCount;
153                 DE_NULL,                               // VkDescriptorSetLayout* pSetLayouts;
154                 0u,                                    // uint32_t pushConstantRangeCount;
155                 DE_NULL,                               // const VkPushConstantRange* pPushConstantRanges;
156                 DE_NULL,                               // const VkSpecializationInfo* pSpecializationInfo;
157             },
158             {
159                 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
160                 DE_NULL,                                      // const void* pNext;
161                 vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,      // VkShaderCreateFlagsEXT flags;
162                 vk::VK_SHADER_STAGE_FRAGMENT_BIT,             // VkShaderStageFlagBits stage;
163                 getNextStage(vk::VK_SHADER_STAGE_FRAGMENT_BIT, features.tessellationShader,
164                              features.geometryShader), // VkShaderStageFlags nextStage;
165                 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,     // VkShaderCodeTypeEXT codeType;
166                 frag.getSize(),                        // size_t codeSize;
167                 frag.getBinary(),                      // const void* pCode;
168                 "main",                                // const char* pName;
169                 0u,                                    // uint32_t setLayoutCount;
170                 DE_NULL,                               // VkDescriptorSetLayout* pSetLayouts;
171                 0u,                                    // uint32_t pushConstantRangeCount;
172                 DE_NULL,                               // const VkPushConstantRange* pPushConstantRanges;
173                 DE_NULL,                               // const VkSpecializationInfo* pSpecializationInfo;
174             },
175         };
176         if (features.tessellationShader)
177         {
178             shaderCreateInfos.push_back({
179                 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
180                 DE_NULL,                                      // const void* pNext;
181                 vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,      // VkShaderCreateFlagsEXT flags;
182                 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage;
183                 getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, features.tessellationShader,
184                              features.geometryShader), // VkShaderStageFlags nextStage;
185                 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,     // VkShaderCodeTypeEXT codeType;
186                 tesc.getSize(),                        // size_t codeSize;
187                 tesc.getBinary(),                      // const void* pCode;
188                 "main",                                // const char* pName;
189                 0u,                                    // uint32_t setLayoutCount;
190                 DE_NULL,                               // VkDescriptorSetLayout* pSetLayouts;
191                 0u,                                    // uint32_t pushConstantRangeCount;
192                 DE_NULL,                               // const VkPushConstantRange* pPushConstantRanges;
193                 DE_NULL,                               // const VkSpecializationInfo* pSpecializationInfo;
194             });
195             shaderCreateInfos.push_back({
196                 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,    // VkStructureType sType;
197                 DE_NULL,                                         // const void* pNext;
198                 vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,         // VkShaderCreateFlagsEXT flags;
199                 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage;
200                 getNextStage(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, features.tessellationShader,
201                              features.geometryShader), // VkShaderStageFlags nextStage;
202                 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,     // VkShaderCodeTypeEXT codeType;
203                 tese.getSize(),                        // size_t codeSize;
204                 tese.getBinary(),                      // const void* pCode;
205                 "main",                                // const char* pName;
206                 0u,                                    // uint32_t setLayoutCount;
207                 DE_NULL,                               // VkDescriptorSetLayout* pSetLayouts;
208                 0u,                                    // uint32_t pushConstantRangeCount;
209                 DE_NULL,                               // const VkPushConstantRange* pPushConstantRanges;
210                 DE_NULL,                               // const VkSpecializationInfo* pSpecializationInfo;
211             });
212         }
213         if (features.geometryShader)
214         {
215             shaderCreateInfos.push_back({
216                 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
217                 DE_NULL,                                      // const void* pNext;
218                 vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,      // VkShaderCreateFlagsEXT flags;
219                 vk::VK_SHADER_STAGE_GEOMETRY_BIT,             // VkShaderStageFlagBits stage;
220                 getNextStage(vk::VK_SHADER_STAGE_GEOMETRY_BIT, features.tessellationShader,
221                              features.geometryShader), // VkShaderStageFlags nextStage;
222                 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,     // VkShaderCodeTypeEXT codeType;
223                 geom.getSize(),                        // size_t codeSize;
224                 geom.getBinary(),                      // const void* pCode;
225                 "main",                                // const char* pName;
226                 0u,                                    // uint32_t setLayoutCount;
227                 DE_NULL,                               // VkDescriptorSetLayout* pSetLayouts;
228                 0u,                                    // uint32_t pushConstantRangeCount;
229                 DE_NULL,                               // const VkPushConstantRange* pPushConstantRanges;
230                 DE_NULL,                               // const VkSpecializationInfo* pSpecializationInfo;
231             });
232         }
233         std::vector<vk::VkShaderEXT> shaders(shaderCreateInfos.size());
234         vk.createShadersEXT(device, (uint32_t)shaderCreateInfos.size(), &shaderCreateInfos[0], DE_NULL, &shaders[0]);
235 
236         for (uint32_t i = 0; i < (uint32_t)shaderCreateInfos.size(); ++i)
237         {
238             if (shaderCreateInfos[i].stage == stage)
239             {
240                 shader = shaders[i];
241             }
242             else
243             {
244                 vk.destroyShaderEXT(device, shaders[i], DE_NULL);
245             }
246         }
247     }
248 
249     return vk::Move<vk::VkShaderEXT>(vk::check<vk::VkShaderEXT>(shader),
250                                      vk::Deleter<vk::VkShaderEXT>(vk, device, DE_NULL));
251 }
252 
253 class ShaderObjectBinaryQueryInstance : public vkt::TestInstance
254 {
255 public:
ShaderObjectBinaryQueryInstance(Context & context,const TestParams params)256     ShaderObjectBinaryQueryInstance(Context &context, const TestParams params)
257         : vkt::TestInstance(context)
258         , m_params(params)
259     {
260     }
~ShaderObjectBinaryQueryInstance(void)261     virtual ~ShaderObjectBinaryQueryInstance(void)
262     {
263     }
264 
265     tcu::TestStatus iterate(void) override;
266 
267 private:
268     TestParams m_params;
269 };
270 
iterate(void)271 tcu::TestStatus ShaderObjectBinaryQueryInstance::iterate(void)
272 {
273     const auto &vkp               = m_context.getPlatformInterface();
274     const vk::VkInstance instance = m_context.getInstance();
275     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
276     const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
277     const vk::DeviceInterface &vk             = m_context.getDeviceInterface();
278     const vk::VkDevice device                 = m_context.getDevice();
279     const uint32_t queueFamilyIndex           = m_context.getUniversalQueueFamilyIndex();
280     const bool tessellationSupported          = m_context.getDeviceFeatures().tessellationShader;
281     const bool geometrySupported              = m_context.getDeviceFeatures().geometryShader;
282 
283     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
284         vk::DescriptorSetLayoutBuilder()
285             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
286             .build(vk, device));
287 
288     vk::VkDescriptorSetLayout layout =
289         (m_params.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT) ? *descriptorSetLayout : VK_NULL_HANDLE;
290 
291     const auto &binaries = m_context.getBinaryCollection();
292     vk::Move<vk::VkShaderEXT> shader =
293         createShader(vk, binaries, device, m_context.getDeviceFeatures(), layout, m_params.linked, m_params.stage);
294 
295     size_t dataSize = 0;
296     vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
297     std::vector<uint8_t> data(dataSize);
298     vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
299 
300     for (uint32_t i = 0; i < 10; ++i)
301     {
302         size_t otherDataSize = 0;
303         std::vector<uint8_t> otherData;
304         if (m_params.queryType == SAME_SHADER)
305         {
306             vk.getShaderBinaryDataEXT(device, *shader, &otherDataSize, DE_NULL);
307             otherData.resize(otherDataSize);
308             vk.getShaderBinaryDataEXT(device, *shader, &otherDataSize, otherData.data());
309         }
310         else if (m_params.queryType == NEW_SHADER)
311         {
312             vk::Move<vk::VkShaderEXT> otherShader = createShader(vk, binaries, device, m_context.getDeviceFeatures(),
313                                                                  layout, m_params.linked, m_params.stage);
314             vk.getShaderBinaryDataEXT(device, *otherShader, &otherDataSize, DE_NULL);
315             otherData.resize(otherDataSize);
316             vk.getShaderBinaryDataEXT(device, *otherShader, &otherDataSize, otherData.data());
317         }
318         else if (m_params.queryType == SHADER_FROM_BINARY)
319         {
320             vk::Move<vk::VkShaderEXT> otherShader = vk::createShaderFromBinary(
321                 vk, device, m_params.stage, dataSize, data.data(), tessellationSupported, geometrySupported, layout);
322             vk.getShaderBinaryDataEXT(device, *otherShader, &otherDataSize, DE_NULL);
323             otherData.resize(otherDataSize);
324             vk.getShaderBinaryDataEXT(device, *otherShader, &otherDataSize, otherData.data());
325         }
326         else if (m_params.queryType == NEW_DEVICE || m_params.queryType == DEVICE_NO_EXTS_FEATURES)
327         {
328             vk::VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeatures = vk::initVulkanStructure();
329             shaderObjectFeatures.shaderObject                                = VK_TRUE;
330             vk::VkPhysicalDeviceFeatures2 features2;
331             std::vector<const char *> extensions;
332 
333             if (m_params.queryType == DEVICE_NO_EXTS_FEATURES)
334             {
335                 features2                             = vk::initVulkanStructure(&shaderObjectFeatures);
336                 features2.features.tessellationShader = tessellationSupported;
337                 features2.features.geometryShader     = geometrySupported;
338                 extensions.push_back("VK_EXT_shader_object");
339             }
340             else
341             {
342                 features2  = m_context.getDeviceFeatures2();
343                 extensions = m_context.getDeviceCreationExtensions();
344             }
345             const float queuePriority = 1.0f;
346 
347             const vk::VkDeviceQueueCreateInfo deviceQueueCI = {
348                 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
349                 DE_NULL,                                        // pNext
350                 (vk::VkDeviceQueueCreateFlags)0u,               // flags
351                 queueFamilyIndex,                               // queueFamilyIndex;
352                 1,                                              // queueCount;
353                 &queuePriority,                                 // pQueuePriorities;
354             };
355 
356             const vk::VkDeviceCreateInfo deviceCreateInfo = {
357                 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType;
358                 &features2,                               // pNext;
359                 0u,                                       // flags
360                 1u,                                       // queueCreateInfoCount;
361                 &deviceQueueCI,                           // pQueueCreateInfos;
362                 0u,                                       // layerCount;
363                 DE_NULL,                                  // ppEnabledLayerNames;
364                 (uint32_t)extensions.size(),              // uint32_t enabledExtensionCount;
365                 extensions.data(),                        // const char* const* ppEnabledExtensionNames;
366                 DE_NULL,                                  // pEnabledFeatures;
367             };
368 
369             vk::Move<vk::VkDevice> otherDevice =
370                 createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance,
371                                    instanceDriver, physicalDevice, &deviceCreateInfo);
372 
373             const vk::Unique<vk::VkDescriptorSetLayout> otherDescriptorSetLayout(
374                 vk::DescriptorSetLayoutBuilder()
375                     .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
376                     .build(vk, *otherDevice));
377 
378             vk::VkDescriptorSetLayout otherLayout =
379                 (m_params.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT) ? *otherDescriptorSetLayout : VK_NULL_HANDLE;
380 
381             vk::Move<vk::VkShaderEXT> otherShader = createShader(vk, binaries, *otherDevice, features2.features,
382                                                                  otherLayout, m_params.linked, m_params.stage);
383             vk.getShaderBinaryDataEXT(*otherDevice, *otherShader, &otherDataSize, DE_NULL);
384             otherData.resize(otherDataSize);
385             vk.getShaderBinaryDataEXT(*otherDevice, *otherShader, &otherDataSize, otherData.data());
386         }
387 
388         if (dataSize != otherDataSize)
389             return tcu::TestStatus::fail("Size not matching");
390 
391         for (uint32_t j = 0; j < dataSize; ++j)
392             if (data[j] != otherData[j])
393                 return tcu::TestStatus::fail("Data not matching");
394     }
395 
396     return tcu::TestStatus::pass("Pass");
397 }
398 
399 class ShaderObjectBinaryQueryCase : public vkt::TestCase
400 {
401 public:
ShaderObjectBinaryQueryCase(tcu::TestContext & testCtx,const std::string & name,TestParams params)402     ShaderObjectBinaryQueryCase(tcu::TestContext &testCtx, const std::string &name, TestParams params)
403         : vkt::TestCase(testCtx, name)
404         , m_params(params)
405     {
406     }
~ShaderObjectBinaryQueryCase(void)407     virtual ~ShaderObjectBinaryQueryCase(void)
408     {
409     }
410 
411     void checkSupport(vkt::Context &context) const override;
412     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const413     TestInstance *createInstance(Context &context) const override
414     {
415         return new ShaderObjectBinaryQueryInstance(context, m_params);
416     }
417 
418 private:
419     TestParams m_params;
420 };
421 
checkSupport(Context & context) const422 void ShaderObjectBinaryQueryCase::checkSupport(Context &context) const
423 {
424     context.requireDeviceFunctionality("VK_EXT_shader_object");
425 
426     if (m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
427         m_params.stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
428         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
429     if (m_params.stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
430         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
431 }
432 
initPrograms(vk::SourceCollections & programCollection) const433 void ShaderObjectBinaryQueryCase::initPrograms(vk::SourceCollections &programCollection) const
434 {
435     vk::addBasicShaderObjectShaders(programCollection);
436 }
437 
438 class ShaderObjectIncompatibleBinaryInstance : public vkt::TestInstance
439 {
440 public:
ShaderObjectIncompatibleBinaryInstance(Context & context,vk::VkShaderStageFlagBits shaderStage,const IncompleteBinaryTestType testType)441     ShaderObjectIncompatibleBinaryInstance(Context &context, vk::VkShaderStageFlagBits shaderStage,
442                                            const IncompleteBinaryTestType testType)
443         : vkt::TestInstance(context)
444         , m_shaderStage(shaderStage)
445         , m_testType(testType)
446     {
447     }
~ShaderObjectIncompatibleBinaryInstance(void)448     virtual ~ShaderObjectIncompatibleBinaryInstance(void)
449     {
450     }
451 
452     tcu::TestStatus iterate(void) override;
453 
454 private:
455     const vk::VkShaderStageFlagBits m_shaderStage;
456     const IncompleteBinaryTestType m_testType;
457 };
458 
iterate(void)459 tcu::TestStatus ShaderObjectIncompatibleBinaryInstance::iterate(void)
460 {
461     const vk::VkInstance instance = m_context.getInstance();
462     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
463     const vk::DeviceInterface &vk    = m_context.getDeviceInterface();
464     const vk::VkDevice device        = m_context.getDevice();
465     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
466     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
467 
468     const auto &binaries = m_context.getBinaryCollection();
469 
470     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
471         vk::DescriptorSetLayoutBuilder()
472             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
473             .build(vk, device));
474 
475     vk::VkDescriptorSetLayout layout =
476         (m_shaderStage == vk::VK_SHADER_STAGE_COMPUTE_BIT) ? *descriptorSetLayout : VK_NULL_HANDLE;
477 
478     const auto &src                                  = binaries.get(getShaderName(m_shaderStage));
479     const vk::VkShaderCreateInfoEXT shaderCreateInfo = {
480         vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
481         DE_NULL,                                      // const void* pNext;
482         0u,                                           // VkShaderCreateFlagsEXT flags;
483         m_shaderStage,                                // VkShaderStageFlagBits stage;
484         vk::getShaderObjectNextStages(m_shaderStage, tessellationSupported,
485                                       geometrySupported), // VkShaderStageFlags nextStage;
486         vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,                // VkShaderCodeTypeEXT codeType;
487         src.getSize(),                                    // size_t codeSize;
488         src.getBinary(),                                  // const void* pCode;
489         "main",                                           // const char* pName;
490         (layout != VK_NULL_HANDLE) ? 1u : 0u,             // uint32_t setLayoutCount;
491         (layout != VK_NULL_HANDLE) ? &layout : DE_NULL,   // VkDescriptorSetLayout* pSetLayouts;
492         0u,                                               // uint32_t pushConstantRangeCount;
493         DE_NULL,                                          // const VkPushConstantRange* pPushConstantRanges;
494         DE_NULL,                                          // const VkSpecializationInfo* pSpecializationInfo;
495     };
496 
497     vk::Move<vk::VkShaderEXT> shader = vk::createShader(vk, device, shaderCreateInfo);
498     size_t dataSize                  = 0;
499     vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
500     std::vector<uint8_t> data(dataSize, 123);
501 
502     if (m_testType == HALF_DATA_SIZE)
503     {
504         dataSize /= 2;
505         vk::VkResult result = vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
506 
507         if (result != vk::VK_INCOMPLETE)
508             return tcu::TestStatus::fail("Result was not VK_INCOMPLETE");
509 
510         for (const auto &byte : data)
511             if (byte != 123)
512                 return tcu::TestStatus::fail("Data was modified");
513 
514         if (dataSize != 0)
515             return tcu::TestStatus::fail("Data size was not 0");
516     }
517     else
518     {
519         de::Random random(102030);
520         // Generate random garbage data
521         if (m_testType != CREATE_FROM_HALF_SIZE)
522         {
523             uint32_t i = m_testType == GARBAGE_DATA ? 0u : (uint32_t)dataSize / 2u;
524             for (; i < dataSize; ++i)
525                 data[i] = random.getUint8();
526         }
527 
528         if (m_testType == CREATE_FROM_HALF_SIZE || m_testType == CREATE_FROM_HALF_SIZE_GARBAGE)
529             dataSize /= 2;
530 
531         const vk::VkShaderCreateInfoEXT invalidShaderCreateInfo = {
532             vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType;
533             DE_NULL,                                      // const void* pNext;
534             0u,                                           // VkShaderCreateFlagsEXT flags;
535             m_shaderStage,                                // VkShaderStageFlagBits stage;
536             vk::getShaderObjectNextStages(m_shaderStage, tessellationSupported,
537                                           geometrySupported), // VkShaderStageFlags nextStage;
538             vk::VK_SHADER_CODE_TYPE_BINARY_EXT,               // VkShaderCodeTypeEXT codeType;
539             dataSize,                                         // size_t codeSize;
540             data.data(),                                      // const void* pCode;
541             "main",                                           // const char* pName;
542             (layout != VK_NULL_HANDLE) ? 1u : 0u,             // uint32_t setLayoutCount;
543             (layout != VK_NULL_HANDLE) ? &layout : DE_NULL,   // VkDescriptorSetLayout* pSetLayouts;
544             0u,                                               // uint32_t pushConstantRangeCount;
545             DE_NULL,                                          // const VkPushConstantRange* pPushConstantRanges;
546             DE_NULL,                                          // const VkSpecializationInfo* pSpecializationInfo;
547         };
548 
549         vk::VkShaderEXT dstShader;
550         vk::VkResult result = vk.createShadersEXT(device, 1u, &invalidShaderCreateInfo, DE_NULL, &dstShader);
551 
552         if (result != vk::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)
553             return tcu::TestStatus::fail("Fail");
554     }
555 
556     return tcu::TestStatus::pass("Pass");
557 }
558 
559 class ShaderObjectIncompatibleBinaryCase : public vkt::TestCase
560 {
561 public:
ShaderObjectIncompatibleBinaryCase(tcu::TestContext & testCtx,const std::string & name,const vk::VkShaderStageFlagBits shaderStage,const IncompleteBinaryTestType testType)562     ShaderObjectIncompatibleBinaryCase(tcu::TestContext &testCtx, const std::string &name,
563                                        const vk::VkShaderStageFlagBits shaderStage,
564                                        const IncompleteBinaryTestType testType)
565         : vkt::TestCase(testCtx, name)
566         , m_shaderStage(shaderStage)
567         , m_testType(testType)
568     {
569     }
~ShaderObjectIncompatibleBinaryCase(void)570     virtual ~ShaderObjectIncompatibleBinaryCase(void)
571     {
572     }
573 
574     void checkSupport(vkt::Context &context) const override;
575     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const576     TestInstance *createInstance(Context &context) const override
577     {
578         return new ShaderObjectIncompatibleBinaryInstance(context, m_shaderStage, m_testType);
579     }
580 
581 private:
582     const vk::VkShaderStageFlagBits m_shaderStage;
583     const IncompleteBinaryTestType m_testType;
584 };
585 
checkSupport(Context & context) const586 void ShaderObjectIncompatibleBinaryCase::checkSupport(Context &context) const
587 {
588     context.requireDeviceFunctionality("VK_EXT_shader_object");
589 
590     if (m_shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
591         m_shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
592         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
593     if (m_shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
594         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
595 }
596 
initPrograms(vk::SourceCollections & programCollection) const597 void ShaderObjectIncompatibleBinaryCase::initPrograms(vk::SourceCollections &programCollection) const
598 {
599     vk::addBasicShaderObjectShaders(programCollection);
600 }
601 
602 class ShaderObjectDeviceFeaturesBinaryInstance : public vkt::TestInstance
603 {
604 public:
ShaderObjectDeviceFeaturesBinaryInstance(Context & context,const bool linked,const vk::VkShaderStageFlagBits stage,const uint32_t index)605     ShaderObjectDeviceFeaturesBinaryInstance(Context &context, const bool linked, const vk::VkShaderStageFlagBits stage,
606                                              const uint32_t index)
607         : vkt::TestInstance(context)
608         , m_linked(linked)
609         , m_stage(stage)
610         , m_index(index)
611     {
612     }
~ShaderObjectDeviceFeaturesBinaryInstance(void)613     virtual ~ShaderObjectDeviceFeaturesBinaryInstance(void)
614     {
615     }
616 
617     tcu::TestStatus iterate(void) override;
618 
619 private:
620     const bool m_linked;
621     const vk::VkShaderStageFlagBits m_stage;
622     const uint32_t m_index;
623 };
624 
findPNext(const void * pNext,vk::VkStructureType sType)625 const void *findPNext(const void *pNext, vk::VkStructureType sType)
626 {
627     while (pNext != DE_NULL)
628     {
629         if (((vk::VkBaseOutStructure *)pNext)->sType == sType)
630             return (const void *)pNext;
631         pNext = ((vk::VkBaseOutStructure *)pNext)->pNext;
632     }
633     return (const void *)DE_NULL;
634 }
635 
iterate(void)636 tcu::TestStatus ShaderObjectDeviceFeaturesBinaryInstance::iterate(void)
637 {
638     const auto &vkp               = m_context.getPlatformInterface();
639     const vk::VkInstance instance = m_context.getInstance();
640     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
641     const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
642     const vk::DeviceInterface &vk             = m_context.getDeviceInterface();
643     const vk::VkDevice device                 = m_context.getDevice();
644     const uint32_t queueFamilyIndex           = m_context.getUniversalQueueFamilyIndex();
645     const auto &binaries                      = m_context.getBinaryCollection();
646 
647     const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
648 
649     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
650         vk::DescriptorSetLayoutBuilder()
651             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
652             .build(vk, device));
653 
654     vk::VkDescriptorSetLayout layout =
655         (m_stage == vk::VK_SHADER_STAGE_COMPUTE_BIT) ? *descriptorSetLayout : VK_NULL_HANDLE;
656 
657     vk::Move<vk::VkShaderEXT> shader = createShader(vk, binaries, device, features, layout, m_linked, m_stage);
658 
659     size_t dataSize = 0;
660     vk.getShaderBinaryDataEXT(device, *shader, &dataSize, DE_NULL);
661     std::vector<uint8_t> data(dataSize);
662     vk.getShaderBinaryDataEXT(device, *shader, &dataSize, data.data());
663 
664     size_t otherDataSize = 0;
665     std::vector<uint8_t> otherData;
666 
667     const vk::VkPhysicalDeviceFeatures2 features2 = m_context.getDeviceFeatures2();
668     vk::VkPhysicalDeviceFeatures2 testFeatures    = m_context.getDeviceFeatures2();
669     std::vector<const char *> extensions          = m_context.getDeviceCreationExtensions();
670 
671     auto shaderObjectFeatures                       = m_context.getShaderObjectFeaturesEXT();
672     auto vulkan11features                           = m_context.getDeviceVulkan11Features();
673     auto vulkan12features                           = m_context.getDeviceVulkan12Features();
674     auto vulkan13features                           = m_context.getDeviceVulkan13Features();
675     auto transformFeedbackFeatures                  = m_context.getTransformFeedbackFeaturesEXT();
676     auto dynamicRenderingFeatures                   = m_context.getDynamicRenderingFeatures();
677     auto cornerSampledImageFeatures                 = m_context.getCornerSampledImageFeatures();
678     auto multiviewFeatures                          = m_context.getMultiviewFeatures();
679     auto shaderDrawParametersFeatures               = m_context.getShaderDrawParametersFeatures();
680     auto textureCompressionAstrHdrFeatures          = m_context.getTextureCompressionASTCHDRFeatures();
681     auto pipelineRobustnessFeatures                 = m_context.getPipelineRobustnessFeaturesEXT();
682     auto conditionalRenderingFeatures               = m_context.getConditionalRenderingFeaturesEXT();
683     auto shaderFloat16Int8Features                  = m_context.getShaderFloat16Int8Features();
684     auto f16BitStorageFeatures                      = m_context.get16BitStorageFeatures();
685     auto depthCilpEnableFeatures                    = m_context.getDepthClipEnableFeaturesEXT();
686     auto imagelessFramebufferFeatures               = m_context.getImagelessFramebufferFeatures();
687     auto performanceQueryFeatures                   = m_context.getPerformanceQueryFeatures();
688     auto variablePointersFeatures                   = m_context.getVariablePointersFeatures();
689     auto inlineUniformBlockFeatures                 = m_context.getInlineUniformBlockFeatures();
690     auto protectedMemoryFeatures                    = m_context.getProtectedMemoryFeatures();
691     auto blendOperationAdvancedFeatures             = m_context.getBlendOperationAdvancedFeaturesEXT();
692     auto accelerationStructureFeatures              = m_context.getAccelerationStructureFeatures();
693     auto smBuiltinFeatures                          = m_context.getShaderSMBuiltinsFeatures();
694     auto samplerYcbcrConversionFeatures             = m_context.getSamplerYcbcrConversionFeatures();
695     auto descriptorIndexingFeatures                 = m_context.getDescriptorIndexingFeatures();
696     auto portabilitySubsetFeatures                  = m_context.getPortabilitySubsetFeatures();
697     auto shadingRateImageFeatures                   = m_context.getShadingRateImageFeatures();
698     auto representativeFragmentTestFeatures         = m_context.getRepresentativeFragmentTestFeatures();
699     auto shaderSubgroupExtnededTypesFeatures        = m_context.getShaderSubgroupExtendedTypesFeatures();
700     auto f8BitStorageFeatures                       = m_context.get8BitStorageFeatures();
701     auto shaderAtomicInt64Features                  = m_context.getShaderAtomicInt64Features();
702     auto shaderClockFeatures                        = m_context.getShaderClockFeatures();
703     auto vertexAttributeDivisorFeatures             = m_context.getVertexAttributeDivisorFeatures();
704     auto computeShaderDerivativesFeatures           = m_context.getComputeShaderDerivativesFeatures();
705     auto meshShaderFeatures                         = m_context.getMeshShaderFeaturesEXT();
706     auto fragmentShaderBarycentricFeatures          = m_context.getFragmentShaderBarycentricFeatures();
707     auto shaderImageFootprintFeatures               = m_context.getShaderImageFootprintFeatures();
708     auto exclusiveScissorFeatures                   = m_context.getExclusiveScissorFeatures();
709     auto timelineSemaphoreFeatures                  = m_context.getTimelineSemaphoreFeatures();
710     auto shaderIntegerFunctions2Features            = m_context.getShaderIntegerFunctions2FeaturesINTEL();
711     auto vulkanMemoryModelFeatures                  = m_context.getVulkanMemoryModelFeatures();
712     auto shaderTerminateInvocationFeatures          = m_context.getShaderTerminateInvocationFeatures();
713     auto fragmentDensityMapFeatures                 = m_context.getFragmentDensityMapFeaturesEXT();
714     auto scalarBlockLayoutFeatures                  = m_context.getScalarBlockLayoutFeatures();
715     auto subgroupSizeControlFeatures                = m_context.getSubgroupSizeControlFeatures();
716     auto coherentMemoryFeatures                     = m_context.getCoherentMemoryFeaturesAMD();
717     auto shaderImageAtomicInt64Features             = m_context.getShaderImageAtomicInt64FeaturesEXT();
718     auto memoryPriorityFeatures                     = m_context.getMemoryPriorityFeaturesEXT();
719     auto dedicatedAllocationImageAliasingFeatures   = m_context.getDedicatedAllocationImageAliasingFeatures();
720     auto separateDepthStencilLayoutFeatures         = m_context.getSeparateDepthStencilLayoutsFeatures();
721     auto bufferDeviceAddressFeatures                = m_context.getBufferDeviceAddressFeatures();
722     auto presentWaitFeatures                        = m_context.getPresentWaitFeatures();
723     auto cooperativeMatrixFeatures                  = m_context.getCooperativeMatrixFeatures();
724     auto coverageReductionModeFeatures              = m_context.getCoverageReductionModeFeatures();
725     auto fragmentShaderInterlockFeatures            = m_context.getFragmentShaderInterlockFeaturesEXT();
726     auto ycbcrImageArraysFeatures                   = m_context.getYcbcrImageArraysFeaturesEXT();
727     auto uniformBufferStandardLayoutFeatures        = m_context.getUniformBufferStandardLayoutFeatures();
728     auto provokingVertexFeatures                    = m_context.getProvokingVertexFeaturesEXT();
729     auto lineRasterizationFeatures                  = m_context.getLineRasterizationFeatures();
730     auto shaderAtomicFloatFeatures                  = m_context.getShaderAtomicFloatFeaturesEXT();
731     auto hostQueryResetFeatures                     = m_context.getHostQueryResetFeatures();
732     auto indexTypeUint8Features                     = m_context.getIndexTypeUint8Features();
733     auto extendedDynamicStateFeatures               = m_context.getExtendedDynamicStateFeaturesEXT();
734     auto pipelineExecutablePropertiesFeatures       = m_context.getPipelineExecutablePropertiesFeatures();
735     auto shaderAtomicFloat2Features                 = m_context.getShaderAtomicFloat2FeaturesEXT();
736     auto swapchainMaitenance1Features               = m_context.getSwapchainMaintenance1FeaturesEXT();
737     auto shaderDemoteToHelperInvocationFeatures     = m_context.getShaderDemoteToHelperInvocationFeatures();
738     auto deviceGeneratedCommandsFeatures            = m_context.getDeviceGeneratedCommandsFeatures();
739     auto inheritedViewportScissorFeatures           = m_context.getInheritedViewportScissorFeatures();
740     auto shaderIntegerDotProductFeatures            = m_context.getShaderIntegerDotProductFeatures();
741     auto texelBufferAlignmentFeatures               = m_context.getTexelBufferAlignmentFeaturesEXT();
742     auto deviceMemoryReportFeatures                 = m_context.getDeviceMemoryReportFeaturesEXT();
743     auto robustness2Features                        = m_context.getRobustness2FeaturesEXT();
744     auto customBorderColorFeatures                  = m_context.getCustomBorderColorFeaturesEXT();
745     auto presentBarrierFeatures                     = m_context.getPresentBarrierFeatures();
746     auto presentIdFeatures                          = m_context.getPresentIdFeatures();
747     auto privateDataFeatures                        = m_context.getPrivateDataFeatures();
748     auto pipelineCreationCacheControlFeatures       = m_context.getPipelineCreationCacheControlFeatures();
749     auto diagnosticConfigFeatures                   = m_context.getDiagnosticsConfigFeatures();
750     auto synchronization2Features                   = m_context.getSynchronization2Features();
751     auto descriptorBufferFeatures                   = m_context.getDescriptorBufferFeaturesEXT();
752     auto graphicsPipelineLibraryFeatures            = m_context.getGraphicsPipelineLibraryFeaturesEXT();
753     auto shaderEarlyAndLateFragmentTestsFeatures    = m_context.getShaderEarlyAndLateFragmentTestsFeaturesAMD();
754     auto shaderSubgroupUniformControlFlowFeatures   = m_context.getShaderSubgroupUniformControlFlowFeatures();
755     auto zeroInitializeWorkgroupMemoryFeatures      = m_context.getZeroInitializeWorkgroupMemoryFeatures();
756     auto fragmentShadingRateEnumsFeatures           = m_context.getFragmentShadingRateEnumsFeatures();
757     auto rayTracingMotionBlurFeatures               = m_context.getRayTracingMotionBlurFeatures();
758     auto ycbcr2Plane444FormatsFeatures              = m_context.getYcbcr2Plane444FormatsFeaturesEXT();
759     auto fragmentDensityMap2Features                = m_context.getFragmentDensityMap2FeaturesEXT();
760     auto imageRobustnessFeatures                    = m_context.getImageRobustnessFeatures();
761     auto workgroupMemoryExplicitLayoutFeatures      = m_context.getWorkgroupMemoryExplicitLayoutFeatures();
762     auto ImageCompressionControlFeatures            = m_context.getImageCompressionControlFeaturesEXT();
763     auto attachmentFeedbackLoopFeatures             = m_context.getAttachmentFeedbackLoopLayoutFeaturesEXT();
764     auto f4444FormatsFeatures                       = m_context.get4444FormatsFeaturesEXT();
765     auto faultFeatures                              = m_context.getFaultFeaturesEXT();
766     auto rasterizationOrderAttachmentAccessFeatures = m_context.getRasterizationOrderAttachmentAccessFeaturesEXT();
767     auto rgba10x6FormatsFeatures                    = m_context.getRGBA10X6FormatsFeaturesEXT();
768     auto rayTracingPipelineFeatures                 = m_context.getRayTracingPipelineFeatures();
769     auto rayQueryFeatures                           = m_context.getRayQueryFeatures();
770     auto mutableDescriptorTypeFeatures              = m_context.getMutableDescriptorTypeFeaturesEXT();
771     auto vertexInputDynamicStateFeatures            = m_context.getVertexInputDynamicStateFeaturesEXT();
772     auto addressBindingReportFeatures               = m_context.getAddressBindingReportFeaturesEXT();
773     auto depthClipControlFeatures                   = m_context.getDepthClipControlFeaturesEXT();
774     auto primitiveTopologyListRestartFeatures       = m_context.getPrimitiveTopologyListRestartFeaturesEXT();
775     auto subpassShadingFeatures                     = m_context.getSubpassShadingFeaturesHUAWEI();
776     auto invocationMaskFeatures                     = m_context.getInvocationMaskFeaturesHUAWEI();
777     auto externalMemoryRDMAFeatures                 = m_context.getExternalMemoryRDMAFeatures();
778     auto pipelinePropertiesFeatures                 = m_context.getPipelinePropertiesFeaturesEXT();
779     auto multisampledRenderToSingleSampledFeatures  = m_context.getMultisampledRenderToSingleSampledFeaturesEXT();
780     auto extendedDynamicState2Features              = m_context.getExtendedDynamicState2FeaturesEXT();
781     auto colorWriteEnableFeatures                   = m_context.getColorWriteEnableFeaturesEXT();
782     auto primitivesGeneratedQueryFeatures           = m_context.getPrimitivesGeneratedQueryFeaturesEXT();
783     auto rayTracingMaintenance1Features             = m_context.getRayTracingMaintenance1Features();
784     auto globalPriorityQueryFeatures                = m_context.getGlobalPriorityQueryFeatures();
785     auto imageViewMinLodFeatures                    = m_context.getImageViewMinLodFeaturesEXT();
786     auto multiDrawFeatures                          = m_context.getMultiDrawFeaturesEXT();
787     auto image2DViewOf3DFeatures                    = m_context.getImage2DViewOf3DFeaturesEXT();
788     auto opacityMicromapFeatures                    = m_context.getOpacityMicromapFeaturesEXT();
789     auto displacementMicromapFeatures               = m_context.getDisplacementMicromapFeatures();
790     auto clusterCullingShaderFeatures               = m_context.getClusterCullingShaderFeaturesHUAWEI();
791     auto borderColorSwizzleFeatures                 = m_context.getBorderColorSwizzleFeaturesEXT();
792     auto pageableDeviceLocalMemoryFeatures          = m_context.getPageableDeviceLocalMemoryFeaturesEXT();
793     auto maintenance4Features                       = m_context.getMaintenance4Features();
794     auto imageSlicedViewOf3DFeatures                = m_context.getImageSlicedViewOf3DFeaturesEXT();
795     auto descriptorSetHostMappingFeatures           = m_context.getDescriptorSetHostMappingFeaturesVALVE();
796     auto depthClampZeroOneFeatures                  = m_context.getDepthClampZeroOneFeaturesEXT();
797     auto nonSeamlessCubeMapFeatures                 = m_context.getNonSeamlessCubeMapFeaturesEXT();
798     auto fragmentDensityMapOffsetFeatures           = m_context.getFragmentDensityMapOffsetFeaturesQCOM();
799     auto copyMemoryIndirectFeatures                 = m_context.getCopyMemoryIndirectFeatures();
800     auto memoryDecompressionFeatures                = m_context.getMemoryDecompressionFeatures();
801     auto linearColorAttachmentFeatures              = m_context.getLinearColorAttachmentFeatures();
802     auto imageCompressionControlFeatures            = m_context.getImageCompressionControlFeaturesEXT();
803     auto imageCompressionControLSwapchainFeatures   = m_context.getImageCompressionControlSwapchainFeaturesEXT();
804     auto imageProcessingFeatures                    = m_context.getImageProcessingFeaturesQCOM();
805     auto extendedDynamicState3Features              = m_context.getExtendedDynamicState3FeaturesEXT();
806     auto subpassMergeFeedbackFeatures               = m_context.getSubpassMergeFeedbackFeaturesEXT();
807     auto shaderModuleIdentifierFeatures             = m_context.getShaderModuleIdentifierFeaturesEXT();
808     auto opticalFlowFeatures                        = m_context.getOpticalFlowFeatures();
809     auto legacyDitheringFeatures                    = m_context.getLegacyDitheringFeaturesEXT();
810     auto pipelineProtectedAccessFeatures            = m_context.getPipelineProtectedAccessFeaturesEXT();
811     auto tilePropertiesFeatures                     = m_context.getTilePropertiesFeaturesQCOM();
812     auto multivewPerViewViewportsFeatures           = m_context.getMultiviewPerViewViewportsFeaturesQCOM();
813     auto rayTracingInvocationReorderFeatures        = m_context.getRayTracingInvocationReorderFeatures();
814     auto shaderCoreBuiltinsFeatures                 = m_context.getShaderCoreBuiltinsFeaturesARM();
815     auto pipelineLibraryGroupHandlesFeatures        = m_context.getPipelineLibraryGroupHandlesFeaturesEXT();
816     auto multivewPerViewRenderAreasFeatures         = m_context.getMultiviewPerViewRenderAreasFeaturesQCOM();
817 
818     // These features depend on other features being enabled
819     meshShaderFeatures.multiviewMeshShader                    = VK_FALSE;
820     meshShaderFeatures.primitiveFragmentShadingRateMeshShader = VK_FALSE;
821 
822     std::vector<void *> pNextFeatures = {
823         &vulkan11features,
824         &vulkan12features,
825         &vulkan13features,
826         &transformFeedbackFeatures,
827         &dynamicRenderingFeatures,
828         &cornerSampledImageFeatures,
829         &multiviewFeatures,
830         &shaderDrawParametersFeatures,
831         &textureCompressionAstrHdrFeatures,
832         &pipelineRobustnessFeatures,
833         &conditionalRenderingFeatures,
834         &shaderFloat16Int8Features,
835         &f16BitStorageFeatures,
836         &depthCilpEnableFeatures,
837         &imagelessFramebufferFeatures,
838         &performanceQueryFeatures,
839         &variablePointersFeatures,
840         &inlineUniformBlockFeatures,
841         &protectedMemoryFeatures,
842         &blendOperationAdvancedFeatures,
843         &accelerationStructureFeatures,
844         &smBuiltinFeatures,
845         &samplerYcbcrConversionFeatures,
846         &descriptorIndexingFeatures,
847         &portabilitySubsetFeatures,
848         &shadingRateImageFeatures,
849         &representativeFragmentTestFeatures,
850         &shaderSubgroupExtnededTypesFeatures,
851         &f8BitStorageFeatures,
852         &shaderAtomicInt64Features,
853         &shaderClockFeatures,
854         &vertexAttributeDivisorFeatures,
855         &computeShaderDerivativesFeatures,
856         &meshShaderFeatures,
857         &fragmentShaderBarycentricFeatures,
858         &shaderImageFootprintFeatures,
859         &exclusiveScissorFeatures,
860         &timelineSemaphoreFeatures,
861         &shaderIntegerFunctions2Features,
862         &vulkanMemoryModelFeatures,
863         &shaderTerminateInvocationFeatures,
864         &fragmentDensityMapFeatures,
865         &scalarBlockLayoutFeatures,
866         &subgroupSizeControlFeatures,
867         &coherentMemoryFeatures,
868         &shaderImageAtomicInt64Features,
869         &memoryPriorityFeatures,
870         &dedicatedAllocationImageAliasingFeatures,
871         &separateDepthStencilLayoutFeatures,
872         &bufferDeviceAddressFeatures,
873         &presentWaitFeatures,
874         &cooperativeMatrixFeatures,
875         &coverageReductionModeFeatures,
876         &fragmentShaderInterlockFeatures,
877         &ycbcrImageArraysFeatures,
878         &uniformBufferStandardLayoutFeatures,
879         &provokingVertexFeatures,
880         &lineRasterizationFeatures,
881         &shaderAtomicFloatFeatures,
882         &hostQueryResetFeatures,
883         &indexTypeUint8Features,
884         &extendedDynamicStateFeatures,
885         &pipelineExecutablePropertiesFeatures,
886         &shaderAtomicFloat2Features,
887         &swapchainMaitenance1Features,
888         &shaderDemoteToHelperInvocationFeatures,
889         &deviceGeneratedCommandsFeatures,
890         &inheritedViewportScissorFeatures,
891         &shaderIntegerDotProductFeatures,
892         &texelBufferAlignmentFeatures,
893         &deviceMemoryReportFeatures,
894         &robustness2Features,
895         &customBorderColorFeatures,
896         &presentBarrierFeatures,
897         &presentIdFeatures,
898         &privateDataFeatures,
899         &pipelineCreationCacheControlFeatures,
900         &diagnosticConfigFeatures,
901         &synchronization2Features,
902         &descriptorBufferFeatures,
903         &graphicsPipelineLibraryFeatures,
904         &shaderEarlyAndLateFragmentTestsFeatures,
905         &shaderSubgroupUniformControlFlowFeatures,
906         &zeroInitializeWorkgroupMemoryFeatures,
907         &fragmentShadingRateEnumsFeatures,
908         &rayTracingMotionBlurFeatures,
909         &ycbcr2Plane444FormatsFeatures,
910         &fragmentDensityMap2Features,
911         &imageRobustnessFeatures,
912         &workgroupMemoryExplicitLayoutFeatures,
913         &ImageCompressionControlFeatures,
914         &attachmentFeedbackLoopFeatures,
915         &f4444FormatsFeatures,
916         &faultFeatures,
917         &rasterizationOrderAttachmentAccessFeatures,
918         &rgba10x6FormatsFeatures,
919         &rayTracingPipelineFeatures,
920         &rayQueryFeatures,
921         &mutableDescriptorTypeFeatures,
922         &vertexInputDynamicStateFeatures,
923         &addressBindingReportFeatures,
924         &depthClipControlFeatures,
925         &primitiveTopologyListRestartFeatures,
926         &subpassShadingFeatures,
927         &invocationMaskFeatures,
928         &externalMemoryRDMAFeatures,
929         &pipelinePropertiesFeatures,
930         &multisampledRenderToSingleSampledFeatures,
931         &extendedDynamicState2Features,
932         &colorWriteEnableFeatures,
933         &primitivesGeneratedQueryFeatures,
934         &rayTracingMaintenance1Features,
935         &globalPriorityQueryFeatures,
936         &imageViewMinLodFeatures,
937         &multiDrawFeatures,
938         &image2DViewOf3DFeatures,
939         &opacityMicromapFeatures,
940         &displacementMicromapFeatures,
941         &clusterCullingShaderFeatures,
942         &borderColorSwizzleFeatures,
943         &pageableDeviceLocalMemoryFeatures,
944         &maintenance4Features,
945         &imageSlicedViewOf3DFeatures,
946         &descriptorSetHostMappingFeatures,
947         &depthClampZeroOneFeatures,
948         &nonSeamlessCubeMapFeatures,
949         &fragmentDensityMapOffsetFeatures,
950         &copyMemoryIndirectFeatures,
951         &memoryDecompressionFeatures,
952         &linearColorAttachmentFeatures,
953         &imageCompressionControlFeatures,
954         &imageCompressionControLSwapchainFeatures,
955         &imageProcessingFeatures,
956         &extendedDynamicState3Features,
957         &subpassMergeFeedbackFeatures,
958         &shaderModuleIdentifierFeatures,
959         &opticalFlowFeatures,
960         &legacyDitheringFeatures,
961         &pipelineProtectedAccessFeatures,
962         &tilePropertiesFeatures,
963         &multivewPerViewViewportsFeatures,
964         &rayTracingInvocationReorderFeatures,
965         &shaderCoreBuiltinsFeatures,
966         &pipelineLibraryGroupHandlesFeatures,
967         &multivewPerViewRenderAreasFeatures,
968     };
969 
970     const float queuePriority = 1.0f;
971 
972     const vk::VkDeviceQueueCreateInfo deviceQueueCI = {
973         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
974         DE_NULL,                                        // pNext
975         (vk::VkDeviceQueueCreateFlags)0u,               // flags
976         queueFamilyIndex,                               // queueFamilyIndex;
977         1,                                              // queueCount;
978         &queuePriority,                                 // pQueuePriorities;
979     };
980 
981     const vk::VkDeviceCreateInfo deviceCreateInfo = {
982         vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType;
983         &testFeatures,                            // pNext;
984         0u,                                       // flags
985         1u,                                       // queueCreateInfoCount;
986         &deviceQueueCI,                           // pQueueCreateInfos;
987         0u,                                       // layerCount;
988         DE_NULL,                                  // ppEnabledLayerNames;
989         (uint32_t)extensions.size(),              // uint32_t enabledExtensionCount;
990         extensions.data(),                        // const char* const* ppEnabledExtensionNames;
991         DE_NULL,                                  // pEnabledFeatures;
992     };
993 
994     const uint32_t coreFeaturesCount  = 50u;
995     const uint32_t pNextFeaturesCount = (uint32_t)pNextFeatures.size();
996 
997     // There are too many features to test every combination, so we group them by step = 10
998     const uint32_t step1          = 10u;
999     const uint32_t step2          = 30u;
1000     const uint32_t count2         = uint32_t(std::pow(2u, pNextFeaturesCount / step2));
1001     vk::VkBool32 *coreFeaturesPtr = &testFeatures.features.robustBufferAccess;
1002 
1003     for (uint32_t i = 0; i < count2; ++i)
1004     {
1005         // Reset features
1006         testFeatures.features = features2.features;
1007         void *pNext           = DE_NULL;
1008         for (uint32_t j = 0; j < coreFeaturesCount; ++j)
1009         {
1010             if (((m_index >> (j / step1)) & 1) == 0)
1011                 coreFeaturesPtr[j] = VK_FALSE;
1012         }
1013         for (uint32_t j = 0; j < pNextFeaturesCount; ++j)
1014         {
1015             if (((i >> (j / step2)) & 1) == 1)
1016             {
1017                 if (findPNext(features2.pNext, ((vk::VkBaseOutStructure *)pNextFeatures[j])->sType))
1018                 {
1019                     ((vk::VkBaseOutStructure *)pNextFeatures[j])->pNext = (vk::VkBaseOutStructure *)pNext;
1020                     pNext                                               = pNextFeatures[j];
1021                 }
1022             }
1023         }
1024 
1025         shaderObjectFeatures.pNext = pNext;
1026         testFeatures.pNext         = &shaderObjectFeatures;
1027         // Geometry and tessellation features must not be modified
1028         testFeatures.features.tessellationShader = features.tessellationShader;
1029         testFeatures.features.geometryShader     = features.geometryShader;
1030 
1031         vk::Move<vk::VkDevice> otherDevice =
1032             createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance,
1033                                instanceDriver, physicalDevice, &deviceCreateInfo);
1034 
1035         const vk::Unique<vk::VkDescriptorSetLayout> otherDescriptorSetLayout(
1036             vk::DescriptorSetLayoutBuilder()
1037                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
1038                 .build(vk, *otherDevice));
1039 
1040         vk::VkDescriptorSetLayout otherLayout =
1041             (m_stage == vk::VK_SHADER_STAGE_COMPUTE_BIT) ? *otherDescriptorSetLayout : VK_NULL_HANDLE;
1042 
1043         vk::Move<vk::VkShaderEXT> otherShader =
1044             createShader(vk, binaries, *otherDevice, features, otherLayout, m_linked, m_stage);
1045         vk.getShaderBinaryDataEXT(*otherDevice, *otherShader, &otherDataSize, DE_NULL);
1046         otherData.resize(otherDataSize);
1047         vk.getShaderBinaryDataEXT(*otherDevice, *otherShader, &otherDataSize, otherData.data());
1048 
1049         if (dataSize != otherDataSize)
1050             return tcu::TestStatus::fail("Size not matching");
1051 
1052         for (uint32_t j = 0; j < dataSize; ++j)
1053             if (data[j] != otherData[j])
1054                 return tcu::TestStatus::fail("Data not matching");
1055     }
1056 
1057     return tcu::TestStatus::pass("Pass");
1058 }
1059 
1060 class ShaderObjectDeviceFeaturesBinaryCase : public vkt::TestCase
1061 {
1062 public:
ShaderObjectDeviceFeaturesBinaryCase(tcu::TestContext & testCtx,const std::string & name,const bool linked,const vk::VkShaderStageFlagBits stage,const uint32_t index)1063     ShaderObjectDeviceFeaturesBinaryCase(tcu::TestContext &testCtx, const std::string &name, const bool linked,
1064                                          const vk::VkShaderStageFlagBits stage, const uint32_t index)
1065         : vkt::TestCase(testCtx, name)
1066         , m_linked(linked)
1067         , m_stage(stage)
1068         , m_index(index)
1069     {
1070     }
~ShaderObjectDeviceFeaturesBinaryCase(void)1071     virtual ~ShaderObjectDeviceFeaturesBinaryCase(void)
1072     {
1073     }
1074 
1075     void checkSupport(vkt::Context &context) const override;
1076     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1077     TestInstance *createInstance(Context &context) const override
1078     {
1079         return new ShaderObjectDeviceFeaturesBinaryInstance(context, m_linked, m_stage, m_index);
1080     }
1081 
1082 private:
1083     const bool m_linked;
1084     const vk::VkShaderStageFlagBits m_stage;
1085     const uint32_t m_index;
1086 };
1087 
checkSupport(Context & context) const1088 void ShaderObjectDeviceFeaturesBinaryCase::checkSupport(Context &context) const
1089 {
1090     context.requireDeviceFunctionality("VK_EXT_shader_object");
1091 
1092     if (m_stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
1093         m_stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1094         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1095     if (m_stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
1096         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1097 }
1098 
initPrograms(vk::SourceCollections & programCollection) const1099 void ShaderObjectDeviceFeaturesBinaryCase::initPrograms(vk::SourceCollections &programCollection) const
1100 {
1101     vk::addBasicShaderObjectShaders(programCollection);
1102 }
1103 
getName(QueryType queryType)1104 std::string getName(QueryType queryType)
1105 {
1106     switch (queryType)
1107     {
1108     case SAME_SHADER:
1109         return "same_shader";
1110         break;
1111     case NEW_SHADER:
1112         return "new_shader";
1113         break;
1114     case SHADER_FROM_BINARY:
1115         return "shader_from_binary";
1116         break;
1117     case NEW_DEVICE:
1118         return "new_device";
1119     case DEVICE_NO_EXTS_FEATURES:
1120         return "device_no_exts_features";
1121     default:
1122         DE_ASSERT(0);
1123         break;
1124     }
1125     return {};
1126 }
1127 
1128 } // namespace
1129 
createShaderObjectBinaryTests(tcu::TestContext & testCtx)1130 tcu::TestCaseGroup *createShaderObjectBinaryTests(tcu::TestContext &testCtx)
1131 {
1132     de::MovePtr<tcu::TestCaseGroup> binaryGroup(new tcu::TestCaseGroup(testCtx, "binary"));
1133 
1134     const struct
1135     {
1136         vk::VkShaderStageFlagBits stage;
1137         const char *name;
1138     } stageTests[] = {
1139         {vk::VK_SHADER_STAGE_VERTEX_BIT, "vert"},
1140         {vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tesc"},
1141         {vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tese"},
1142         {vk::VK_SHADER_STAGE_GEOMETRY_BIT, "geom"},
1143         {vk::VK_SHADER_STAGE_FRAGMENT_BIT, "frag"},
1144         {vk::VK_SHADER_STAGE_COMPUTE_BIT, "comp"},
1145     };
1146 
1147     const bool linkedTests[] = {
1148         false,
1149         true,
1150     };
1151 
1152     const QueryType queryTypeTests[] = {
1153         SAME_SHADER, NEW_SHADER, SHADER_FROM_BINARY, NEW_DEVICE, DEVICE_NO_EXTS_FEATURES,
1154     };
1155 
1156     de::MovePtr<tcu::TestCaseGroup> queryGroup(new tcu::TestCaseGroup(testCtx, "query"));
1157     for (const auto &stage : stageTests)
1158     {
1159         de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name));
1160         for (const auto &linked : linkedTests)
1161         {
1162             if (linked && stage.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT)
1163                 continue;
1164 
1165             std::string linkedName = linked ? "linked" : "unlinked";
1166             de::MovePtr<tcu::TestCaseGroup> linkedGroup(new tcu::TestCaseGroup(testCtx, linkedName.c_str()));
1167             for (const auto &queryType : queryTypeTests)
1168             {
1169                 TestParams params = {
1170                     stage.stage,
1171                     linked,
1172                     queryType,
1173                 };
1174                 linkedGroup->addChild(new ShaderObjectBinaryQueryCase(testCtx, getName(queryType), params));
1175             }
1176             stageGroup->addChild(linkedGroup.release());
1177         }
1178         queryGroup->addChild(stageGroup.release());
1179     }
1180 
1181     const struct
1182     {
1183         IncompleteBinaryTestType type;
1184         const char *name;
1185     } incompatibleTests[] = {
1186         {
1187             HALF_DATA_SIZE,
1188             "half_size",
1189         },
1190         {
1191             GARBAGE_DATA,
1192             "garbage_data",
1193         },
1194         {
1195             GARBAGE_SECOND_HALF,
1196             "garbage_second_half",
1197         },
1198         {CREATE_FROM_HALF_SIZE, "create_from_half_size"},
1199         {CREATE_FROM_HALF_SIZE_GARBAGE, "create_from_half_size_garbage"},
1200     };
1201 
1202     de::MovePtr<tcu::TestCaseGroup> incompatibleGroup(new tcu::TestCaseGroup(testCtx, "incompatible"));
1203     for (const auto &stage : stageTests)
1204     {
1205         de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name));
1206         for (const auto &testType : incompatibleTests)
1207         {
1208             stageGroup->addChild(
1209                 new ShaderObjectIncompatibleBinaryCase(testCtx, testType.name, stage.stage, testType.type));
1210         }
1211         incompatibleGroup->addChild(stageGroup.release());
1212     }
1213 
1214     de::MovePtr<tcu::TestCaseGroup> deviceFeaturesGroup(new tcu::TestCaseGroup(testCtx, "device_features"));
1215     for (const auto &stage : stageTests)
1216     {
1217         de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name));
1218         for (const auto &linked : linkedTests)
1219         {
1220             if (linked && stage.stage == vk::VK_SHADER_STAGE_COMPUTE_BIT)
1221                 continue;
1222 
1223             std::string linkedName = linked ? "linked" : "unlinked";
1224             de::MovePtr<tcu::TestCaseGroup> linkedGroup(new tcu::TestCaseGroup(testCtx, linkedName.c_str()));
1225             for (uint32_t i = 0; i < 32; ++i)
1226             {
1227                 linkedGroup->addChild(
1228                     new ShaderObjectDeviceFeaturesBinaryCase(testCtx, std::to_string(i), linked, stage.stage, i));
1229             }
1230             stageGroup->addChild(linkedGroup.release());
1231         }
1232         deviceFeaturesGroup->addChild(stageGroup.release());
1233     }
1234 
1235     binaryGroup->addChild(queryGroup.release());
1236     binaryGroup->addChild(incompatibleGroup.release());
1237     binaryGroup->addChild(deviceFeaturesGroup.release());
1238 
1239     return binaryGroup.release();
1240 }
1241 
1242 } // namespace ShaderObject
1243 } // namespace vkt
1244