Errors when creating shader's modules

Hi!
I’m new to vulkan and I don’t understand this validation errors messages :

validation layer: vkCreateShaderModule(): SPIR-V Capability DrawParameters was declared, but one of the following requirements is required (VkPhysicalDeviceVulkan11Features::shaderDrawParameters OR VK_KHR_shader_draw_parameters).
The Vulkan spec states: If pCode is a pointer to SPIR-V code, and pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.4.309.0/windows/antora/spec/latest/chapters/shaders.html#VUID-VkShaderModuleCreateInfo-pCode-08740)
validation layer: vkCreateShaderModule(): SPIR-V Capability RuntimeDescriptorArray was declared, but one of the following requirements is required (VkPhysicalDeviceVulkan12Features::runtimeDescriptorArray).
The Vulkan spec states: If pCode is a pointer to SPIR-V code, and pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.4.309.0/windows/antora/spec/latest/chapters/shaders.html#VUID-VkShaderModuleCreateInfo-pCode-08740)
validation layer: vkCreateShaderModule(): SPIR-V Extension SPV_EXT_descriptor_indexing was declared, but one of the following requirements is required (1.2.0 (0x00402000) or VK_EXT_descriptor_indexing).
The Vulkan spec states: If pCode is a pointer to SPIR-V code, and pCode declares any of the SPIR-V extensions listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.4.309.0/windows/antora/spec/latest/chapters/shaders.html#VUID-VkShaderModuleCreateInfo-pCode-08742)

When I use basic shaders it works fine but when I want to use this shaders :

void PerPixelLinkedListRenderComponent::compileShaders() {
            const std::string indirectDrawVertexShader = R"(#version 460
                                                            #define M_PI 3.1415926535897932384626433832795
                                                            #define FPI M_PI/4
                                                            layout (location = 0) in vec3 position;
                                                            layout (location = 1) in vec4 color;
                                                            layout (location = 2) in vec2 texCoords;
                                                            layout (location = 3) in vec3 normals;
                                                            layout (push_constant) uniform PushConsts {
                                                                mat4 projectionMatrix;
                                                                mat4 viewMatrix;
                                                                vec4 resolution;
                                                                float time;
                                                            } pushConsts;
                                                            struct ModelData {
                                                                mat4 modelMatrix;
                                                            };
                                                            struct MaterialData {
                                                                uint textureIndex;
                                                                uint materialType;
                                                            };
                                                            layout(set = 0, binding = 4) buffer modelData {
                                                                ModelData modelDatas[];
                                                            };
                                                            layout(set = 0, binding = 5) buffer materialData {
                                                                MaterialData materialDatas[];
                                                            };
                                                            layout(location = 0) out vec2 fTexCoords;
                                                            layout(location = 1) out vec4 frontColor;
                                                            layout(location = 2) out uint texIndex;
                                                            void main() {
                                                                MaterialData materialData = materialDatas[gl_DrawID];
                                                                ModelData modelData = modelDatas[gl_InstanceIndex];
                                                                float xOff = 0;
                                                                float yOff = 0;
                                                                if (materialData.materialType == 1) {
                                                                    yOff = 0.05*sin(position.x*12+pushConsts.time*FPI)*pushConsts.resolution.y;
                                                                    xOff = 0.025*cos(position.x*12+pushConsts.time*FPI)*pushConsts.resolution.x;
                                                                }
                                                                uint textureIndex =  materialData.textureIndex;
                                                                gl_Position = pushConsts.projectionMatrix * pushConsts.viewMatrix * modelData.modelMatrix * vec4((position.x - xOff), (position.y + yOff), position.z, 1.f);
                                                                fTexCoords = texCoords;
                                                                frontColor = color;
                                                                texIndex = textureIndex;
                                                            }
                                                            )";
                const std::string  simpleVertexShader = R"(#version 460
                                                        layout (location = 0) in vec3 position;
                                                        layout (location = 1) in vec4 color;
                                                        layout (location = 2) in vec2 texCoords;
                                                        layout (location = 3) in vec3 normals;
                                                        layout (push_constant) uniform PushConsts {
                                                            mat4 projectionMatrix;
                                                            mat4 viewMatrix;
                                                            mat4 worldMat;
                                                        } pushConsts;
                                                        void main () {
                                                            gl_Position = pushConsts.projectionMatrix * pushConsts.viewMatrix * pushConsts.worldMat * vec4(position, 1.f);
                                                        })";
                const std::string fragmentShader = R"(#version 460
                                                      #extension GL_EXT_nonuniform_qualifier : enable
                                                      struct NodeType {
                                                          vec4 color;
                                                          float depth;
                                                          uint next;
                                                      };
                                                      layout(set = 0, binding = 0) buffer CounterSSBO {
                                                          uint count;
                                                          uint maxNodes;
                                                      };
                                                      layout(set = 0, binding = 1, r32ui) uniform coherent uimage2D headPointers;
                                                      layout(set = 0, binding = 2) buffer LinkedLists {
                                                          NodeType nodes[];
                                                      };
                                                      layout(set = 0, binding = 3) uniform sampler2D textures[];
                                                      layout(location = 0) in vec4 frontColor;
                                                      layout(location = 1) in vec2 fTexCoords;
                                                      layout(location = 2) in flat uint texIndex;
                                                      layout (location = 0) out vec4 fcolor;
                                                      void main() {
                                                           uint nodeIdx = atomicAdd(count, 1);
                                                           vec4 color = (texIndex != 0) ? frontColor * texture(textures[texIndex-1], fTexCoords.xy) : frontColor;
                                                           if (nodeIdx < maxNodes) {
                                                                uint prevHead = imageAtomicExchange(headPointers, ivec2(gl_FragCoord.xy), nodeIdx);
                                                                nodes[nodeIdx].color = color;
                                                                nodes[nodeIdx].depth = gl_FragCoord.z;
                                                                nodes[nodeIdx].next = prevHead;
                                                           }
                                                           //fcolor = vec4(0, 0, 0, 0);
                                                      })";
                 const std::string fragmentShader2 =
                                                   R"(
                                                   #version 460
                                                   #define MAX_FRAGMENTS 20
                                                   struct NodeType {
                                                      vec4 color;
                                                      float depth;
                                                      uint next;
                                                   };
                                                   layout(set = 0, binding = 0, r32ui) uniform coherent uimage2D headPointers;
                                                   layout(set = 0, binding = 1) buffer linkedLists {
                                                       NodeType nodes[];
                                                   };
                                                   layout(location = 0) out vec4 fcolor;
                                                   void main() {
                                                      NodeType frags[MAX_FRAGMENTS];
                                                      int count = 0;
                                                      uint n = imageLoad(headPointers, ivec2(gl_FragCoord.xy)).r;
                                                      while( n != 0xffffffffu && count < MAX_FRAGMENTS) {
                                                           frags[count] = nodes[n];
                                                           n = frags[count].next;
                                                           count++;
                                                      }
                                                      //Bubble sort.
                                                      for (int i = 0; i < count - 1; i++) {
                                                        for (int j = i + 1; j > 0; j--) {
                                                            if (frags[j - 1].depth > frags[j].depth) {
                                                                NodeType tmp = frags[j - 1];
                                                                frags[j - 1] = frags[j];
                                                                frags[j] = tmp;
                                                            }
                                                        }
                                                      }
                                                      vec4 color = vec4(0, 0, 0, 0);
                                                      for( int i = 0; i < count; i++)
                                                      {
                                                        color.rgb = frags[i].color.rgb * frags[i].color.a + color.rgb * (1 - frags[i].color.a);
                                                        color.a = frags[i].color.a + color.a * (1 - frags[i].color.a);
                                                        //color = mix (color, frags[i].color, frags[i].color.a);
                                                      }
                                                      fcolor = color;
                                                   })";
            if (!perPixelLinkedListP2.loadFromMemory(simpleVertexShader, fragmentShader2)) {
                throw core::Erreur(55, "Failed to load per pixel linked list pass 2 shader");
            }
            if (!indirectRenderingShader.loadFromMemory(indirectDrawVertexShader, fragmentShader)) {
                throw core::Erreur(57, "Failed to load indirect rendering shader");
            }

            math::Matrix4f viewMatrix = getWindow().getDefaultView().getViewMatrix().getMatrix().transpose();
            math::Matrix4f projMatrix = getWindow().getDefaultView().getProjMatrix().getMatrix().transpose();
            ppll2PushConsts.viewMatrix = viewMatrix;
            ppll2PushConsts.projMatrix = projMatrix;
            indirectDrawPushConsts.resolution = resolution;
        }

I get all this validation errors messages. I haven’t any problem with the openGL code so why ?
I use indirect rendering…

EDIT : It seems I’ve to add SPIR-V extension in the vulkan code but how to do this ?

Thanks.

I’ve found this link I think it can help me : Enabling Extensions :: Vulkan Documentation Project

Ok Features not supported I think I’ll return to openGL because SamplerArrays and gl_DrawID are supported in opengl but not in vulkan apparently this code is returning false :

VkPhysicalDeviceFeatures supportedFeatures;
                vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
                VkPhysicalDeviceFeatures2 physical_features2 = {};
                physical_features2.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;

                VkPhysicalDeviceVulkan11Features features11 = {};
                physical_features2.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);

                VkPhysicalDeviceVulkan12Features features12 = {};
                physical_features2.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);
                if (features11.shaderDrawParameters == VK_TRUE) {
                    std::cout<<"shader draw parameterrs ok"<<std::endl;
                }
                if (features12.runtimeDescriptorArray == VK_TRUE) {
                    std::cout<<"shader draw parameterrs ok"<<std::endl;
                }
                return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy && features11.shaderDrawParameters == VK_TRUE && features12.runtimeDescriptorArray == VK_TRUE;

And I don’t know how to enable several features, this code returns an error :

VkPhysicalDeviceFeatures deviceFeatures{};
                deviceFeatures.samplerAnisotropy = VK_TRUE;
                VkPhysicalDeviceVulkan11Features features11 = {};
                VkPhysicalDeviceVulkan12Features features12 = {};


                std::vector<VkPhysicalDeviceFeatures2> physical_features2;
                VkPhysicalDeviceFeatures2 physical_features21;
                physical_features21.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
                physical_features21.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(physicalDevice, &physical_features21);
                physical_features2.push_back(physical_features21);
                VkPhysicalDeviceFeatures2 physical_features22;
                physical_features22.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
                physical_features21.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(physicalDevice, &physical_features22);
                physical_features2.push_back(physical_features22);

                VkDeviceCreateInfo createInfo{};
                createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
                createInfo.pNext = physical_features2.data();

                createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
                createInfo.pQueueCreateInfos = queueCreateInfos.data();

                createInfo.pEnabledFeatures = &deviceFeatures;

                createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
                createInfo.ppEnabledExtensionNames = deviceExtensions.data();

                if (enableValidationLayers) {
                    createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
                    createInfo.ppEnabledLayerNames = validationLayers.data();
                } else {
                    createInfo.enabledLayerCount = 0;
                }

                if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
                    throw core::Erreur(0, "failed to create logical device!", 1);
                }

Hi, there is something missing in the documentation we need to specify the sType for 11 and 12 features, I changed my code and now it tells me that features are supported.

bool Device::isDeviceSuitable(VkPhysicalDevice device,  VkSurfaceKHR surface) {
            QueueFamilyIndices indices = findQueueFamilies(device, surface);
            if (surface != VK_NULL_HANDLE) {
                bool extensionsSupported = checkDeviceExtensionSupport(device);
                bool swapChainAdequate;
                if (extensionsSupported) {
                    SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, surface);
                    swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
                } else {
                    swapChainAdequate = true;
                }
                VkPhysicalDeviceFeatures supportedFeatures;
                vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
                VkPhysicalDeviceFeatures2 physical_features2 = {};
                physical_features2.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;

                VkPhysicalDeviceVulkan11Features features11 = {};
                features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
                physical_features2.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);

                VkPhysicalDeviceVulkan12Features features12 = {};
                features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
                physical_features2.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);
                return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy && features11.shaderDrawParameters == VK_TRUE && features12.runtimeDescriptorArray == VK_TRUE;
            } else {
                QueueFamilyIndices  indices = findQueueFamilies(device, surface);
                VkPhysicalDeviceFeatures supportedFeatures;
                vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
                VkPhysicalDeviceFeatures2 physical_features2 = {};

                VkPhysicalDeviceVulkan11Features features11 = {};
                features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
                physical_features2.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);

                VkPhysicalDeviceVulkan12Features features12 = {};
                features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
                physical_features2.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);
                return indices.isGraphicComplete() && supportedFeatures.samplerAnisotropy && features11.shaderDrawParameters == VK_TRUE && features12.runtimeDescriptorArray == VK_TRUE;
            }
        }

But I’ve still a problem here, I don’t know how to enable several features it’s not written in the documentation it seems that pNext can only point to one feature here :

bool Device::isDeviceSuitable(VkPhysicalDevice device,  VkSurfaceKHR surface) {
            QueueFamilyIndices indices = findQueueFamilies(device, surface);
            if (surface != VK_NULL_HANDLE) {
                bool extensionsSupported = checkDeviceExtensionSupport(device);
                bool swapChainAdequate;
                if (extensionsSupported) {
                    SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, surface);
                    swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
                } else {
                    swapChainAdequate = true;
                }
                VkPhysicalDeviceFeatures supportedFeatures;
                vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
                VkPhysicalDeviceFeatures2 physical_features2 = {};
                physical_features2.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;

                VkPhysicalDeviceVulkan11Features features11 = {};
                features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
                physical_features2.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);

                VkPhysicalDeviceVulkan12Features features12 = {};
                features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
                physical_features2.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);
                return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy && features11.shaderDrawParameters == VK_TRUE && features12.runtimeDescriptorArray == VK_TRUE;
            } else {
                QueueFamilyIndices  indices = findQueueFamilies(device, surface);
                VkPhysicalDeviceFeatures supportedFeatures;
                vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
                VkPhysicalDeviceFeatures2 physical_features2 = {};

                VkPhysicalDeviceVulkan11Features features11 = {};
                features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
                physical_features2.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);

                VkPhysicalDeviceVulkan12Features features12 = {};
                features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
                physical_features2.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(device, &physical_features2);
                return indices.isGraphicComplete() && supportedFeatures.samplerAnisotropy && features11.shaderDrawParameters == VK_TRUE && features12.runtimeDescriptorArray == VK_TRUE;
            }
        }

I’ve still the errors which tells me that runtimeDescriptorArrays are not enabled but for shaderDrawArrays the message disappeared.

How to enable several features ?

Thanks.

From the standard:

Any parameter that is a structure containing a sType member must have a value of sType which is a valid VkStructureType value matching the type of the structure.

This applies universally to all Vulcan functions. It is also true of structures in a pNext chain.

Remember back when you learned about linked lists, they often called the pointer to the next element next or some variation thereof? pNext is named because it’s a pointer to the “next element” in a linked list of structures. Each feature struct is a node in a linked list.

But you didn’t build a linked list; you just overwrite the physical_features2.pNext with different values. You’re supposed to build a list, with each node pointing to the next.

Ah ok I tried this :

VkPhysicalDeviceFeatures deviceFeatures{};
                deviceFeatures.samplerAnisotropy = VK_TRUE;
                VkPhysicalDeviceVulkan11Features features11 = {};
                features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
                VkPhysicalDeviceVulkan12Features features12 = {};
                features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;


                VkPhysicalDeviceFeatures2 physical_features21;
                physical_features21.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
                physical_features21.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(physicalDevice, &physical_features21);

                VkPhysicalDeviceFeatures2 physical_features22;
                physical_features22.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
                physical_features22.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(physicalDevice, &physical_features22);

                features12.pNext = &physical_features22;


                VkDeviceCreateInfo createInfo{};
                createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
                createInfo.pNext = &physical_features21;

                createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
                createInfo.pQueueCreateInfos = queueCreateInfos.data();

                createInfo.pEnabledFeatures = VK_NULL_HANDLE;

                createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
                createInfo.ppEnabledExtensionNames = deviceExtensions.data();

                if (enableValidationLayers) {
                    createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
                    createInfo.ppEnabledLayerNames = validationLayers.data();
                } else {
                    createInfo.enabledLayerCount = 0;
                }

                if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
                    throw core::Erreur(0, "failed to create logical device!", 1);
                }

But I’ve still this error :

validation layer: vkCreateShaderModule(): SPIR-V Capability RuntimeDescriptorArray was declared, but one of the following requirements is required (VkPhysicalDeviceVulkan12Features::runtimeDescriptorArray).
The Vulkan spec states: If pCode is a pointer to SPIR-V code, and pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.4.309.0/windows/antora/spec/latest/chapters/shaders.html#VUID-VkShaderModuleCreateInfo-pCode-08740)
validation layer: vkCreatePipelineLayout(): pCreateInfo->flags contains flag bits (0xbaadf00d) which are not recognized members of VkPipelineLayoutCreateFlagBits.

And when I put this :

features11.pNext = &physical_features22;

I’ve this validation error message :

validation layer: vkCreateDevice(): pCreateInfo->pNext chain contains duplicate structure types: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 appears multiple times.
The Vulkan spec states: The sType value of each struct in the pNext chain must be unique, with the exception of structures of type VkDeviceDeviceMemoryReportCreateInfoEXT or VkDevicePrivateDataCreateInfo (https://vulkan.lunarg.com/doc/view/1.4.309.0/windows/antora/spec/latest/chapters/devsandqueues.html#VUID-VkDeviceCreateInfo-sType-unique)

I’m forced to use this struct two times if I want to activate both features so what should I pass to pNext ?

Thanks.

Ok I’ve found how to do this :

VkPhysicalDeviceFeatures deviceFeatures{};
                deviceFeatures.samplerAnisotropy = VK_TRUE;
                VkPhysicalDeviceVulkan11Features features11 = {};
                features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
                VkPhysicalDeviceVulkan12Features features12 = {};
                features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;


                VkPhysicalDeviceFeatures2 physical_features21;
                physical_features21.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
                physical_features21.pNext = &features11;
                vkGetPhysicalDeviceFeatures2(physicalDevice, &physical_features21);

                VkPhysicalDeviceFeatures2 physical_features22;
                physical_features22.sType =  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
                physical_features22.pNext = &features12;
                vkGetPhysicalDeviceFeatures2(physicalDevice, &physical_features22);

                features11.pNext = &features12;


                VkDeviceCreateInfo createInfo{};
                createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
                createInfo.pNext = &physical_features21;

                createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
                createInfo.pQueueCreateInfos = queueCreateInfos.data();

                createInfo.pEnabledFeatures = VK_NULL_HANDLE;

                createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
                createInfo.ppEnabledExtensionNames = deviceExtensions.data();

                if (enableValidationLayers) {
                    createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
                    createInfo.ppEnabledLayerNames = validationLayers.data();
                } else {
                    createInfo.enabledLayerCount = 0;
                }

                if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
                    throw core::Erreur(0, "failed to create logical device!", 1);
                }

Thanks!!!
Solved!!!