0

我真的不明白验证错误是什么意思。中的顶点着色器属性没有对齐要求VkPhysicalDeviceLimits

这是完整的错误:[2022-02-07.20:42:38]:验证错误:[VUID-vkCmdDrawIndexed-None-02721] 对象 0:句柄 = 0xfef35a00000000a0,类型 = VK_OBJECT_TYPE_BUFFER;对象 1:句柄 = 0xa56ac00000000d4,类型 = VK_OBJECT_TYPE_PIPELINE;| 消息 ID = 0x24afafc5 | vkCmdDrawIndexed:顶点属性 0、VK_FORMAT_R32G32B32_SFLOAT、来自 VkPipeline 0xa56ac00000000d4[] 和顶点 VkBuffer 0xfef35a00000000a0[] 的 attribAddress 对齐无效。Vulkan 规范规定:对于给定的顶点缓冲区绑定,获取的任何属性数据都必须完全包含在相应的顶点缓冲区绑定中,如顶点输入描述 ( https://vulkan.lunarg.com/doc/view/1.2. 198.1/windows/1.2-extensions/vkspec.html#VUID-vkCmdDrawIndexed-None-02721

这是我的着色器。

#version 450 core

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inTexCoord;

// Instancing Data
//layout (location = 3) in vec2 XYOffset;

layout (binding = 0) uniform View_Projection {
    mat4 u_View;
    mat4 u_Projection;
};

layout (binding = 1) uniform Model {
    mat4 u_Model;
    mat4 u_NormalModel; // transpose(inverse(u_Model))
};

layout (location = 0) out vec3 Normal;
layout (location = 1) out vec2 TexCoord;

void main() {
    Normal = mat3(u_NormalModel) * inNormal;
    TexCoord = inTexCoord;
    //vec4 InstancePosition = vec4(inPosition.xy + XYOffset, inPosition.z, 1.0);
    //gl_Position = u_Projection * u_View * u_Model * InstancePosition;
    gl_Position = u_Projection * u_View * u_Model * vec4(inPosition, 1.0);
}

更新 1:

struct VulkanPipelineVertexInput
{
    VkPipelineVertexInputStateCreateInfo createInfo;
    std::vector<VkVertexInputBindingDescription> binding_descriptions;
    std::vector<VkVertexInputAttributeDescription> attribute_descriptions;
    std::vector<VkVertexInputBindingDivisorDescriptionEXT> divisor_description;
    VkPipelineVertexInputDivisorStateCreateInfoEXT divisorCreateInfo;
};

static VulkanPipelineVertexInput Vulkan_Internal_PipelineState_InitalizeVertexInput(IPipelineLayout layout)
{
    VulkanPipelineVertexInput input_state;

    PipelineVertexInputDescription &input_description = layout->m_vertex_input_description;
    if(input_description.m_input_elements.size() > 0)
    {
        int lastBinding = -1;
        for(const auto& element : input_description.m_input_elements)
        {
            VkVertexInputAttributeDescription attribute;
            attribute.binding = element.m_binding_id;
            attribute.format = element.m_vk_format;
            attribute.location = element.m_location;
            attribute.offset = element.m_offset;
            input_state.attribute_descriptions.push_back(attribute);
            if(lastBinding != element.m_binding_id)
            {
                lastBinding = element.m_binding_id;
                VkVertexInputBindingDescription binding_description;
                binding_description.binding = element.m_binding_id;
                binding_description.inputRate = element.m_per_instance ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
                binding_description.stride = element.m_stride;
                if(element.m_per_instance)
                {
                    VkVertexInputBindingDivisorDescriptionEXT divisor_description;
                    divisor_description.binding = element.m_binding_id;
                    divisor_description.divisor = element.m_divisor_rate;
                    input_state.divisor_description.push_back(divisor_description);
                }
                input_state.binding_descriptions.push_back(binding_description);
            }
        }
    }

    input_state.createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
    input_state.createInfo.pNext = input_state.divisor_description.size() > 0 ? &input_state.divisorCreateInfo : nullptr;
    input_state.createInfo.flags = 0;
    input_state.createInfo.vertexBindingDescriptionCount = input_state.binding_descriptions.size();
    input_state.createInfo.pVertexBindingDescriptions = input_state.binding_descriptions.data();
    input_state.createInfo.vertexAttributeDescriptionCount = input_state.attribute_descriptions.size();
    input_state.createInfo.pVertexAttributeDescriptions = input_state.attribute_descriptions.data();
    return input_state;
} 

更新 2: 此代码确实渲染,但是一些几何图形被移动了。

渲染输出

4

2 回答 2

0

顶点属性必须在基本类型上自然对齐。因为VK_FORMAT_R32G32B32_SFLOAT这意味着一个 4 字节的边界。

Vulkan 1.3 规范中的第 22.4.1 节:

对于每个属性,原始数据从 ' 开始提取,attribAddress并根据格式的基本类型从 VkVertexInputAttributeDescription' 格式转换为浮点、无符号整数或有符号整数;格式的基本类型必须与着色器中输入变量的基本类型匹配。当且仅当 format 是 64 位数据类型时,着色器中的输入变量必须声明为 64 位数据类型。如果 format 是打包格式,则attribAddress必须是打包格式中描述的整个属性数据类型的字节大小的倍数。否则,attribAddress必须是格式指示的组件类型的字节大小的倍数(请参阅格式)。

于 2022-02-08T08:28:10.760 回答
0

https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3733

我想到了!!!!!!!!!我认为这是一个驱动程序错误。

我在 RenderDoc 中打开程序,它显示顶点缓冲区的偏移量为 1

问题是设置vkCmdSetVertexBuffers错误。即使您不使用它们,也vkCmdSetVertexBuffers需要一个数组。VkDeviceSize[] pOffsets我打错了,写VkDeviceSize[1] pOffsets = {1}而不是VkDeviceSize[1] = {0}

于 2022-02-08T20:48:29.530 回答