0

I really do not understand what the validation error means. There is no alignment requirement for vertex shader attributes in VkPhysicalDeviceLimits.

Here is the full error: [2022-02-07.20:42:38]: Validation Error: [ VUID-vkCmdDrawIndexed-None-02721 ] Object 0: handle = 0xfef35a00000000a0, type = VK_OBJECT_TYPE_BUFFER; Object 1: handle = 0xa56ac00000000d4, type = VK_OBJECT_TYPE_PIPELINE; | MessageID = 0x24afafc5 | vkCmdDrawIndexed: Invalid attribAddress alignment for vertex attribute 0, VK_FORMAT_R32G32B32_SFLOAT,from of VkPipeline 0xa56ac00000000d4[] and vertex VkBuffer 0xfef35a00000000a0[]. The Vulkan spec states: For a given vertex buffer binding, any attribute data fetched must be entirely contained within the corresponding vertex buffer binding, as described in Vertex Input Description (https://vulkan.lunarg.com/doc/view/1.2.198.1/windows/1.2-extensions/vkspec.html#VUID-vkCmdDrawIndexed-None-02721)

Here is my shader.

#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);
}

UPDATE 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;
} 

UPDATE 2: This code does render, however some geometry is shifted.

Render Output

Youssef
  • 1
  • 1
  • 2

2 Answers2

0

Vertex attributes must be naturally aligned on the primitive type. For VK_FORMAT_R32G32B32_SFLOAT this means a 4 byte boundary.

Section 22.4.1 in the Vulkan 1.3 spec:

For each attribute, raw data is extracted starting at attribAddress and is converted from the VkVertexInputAttributeDescription’s format to either floating-point, unsigned integer, or signed integer based on the base type of the format; the base type of the format must match the base type of the input variable in the shader. The input variable in the shader must be declared as a 64-bit data type if and only if format is a 64-bit data type. If format is a packed format, attribAddress must be a multiple of the size in bytes of the whole attribute data type as described in Packed Formats. Otherwise, attribAddress must be a multiple of the size in bytes of the component type indicated by format (see Formats).

solidpixel
  • 10,688
  • 1
  • 20
  • 33
0

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

I figured it out!!!!!!!!! I thought this was a driver bug.

I opened the program in RenderDoc and it showed that the vertex buffer had an offset of 1

The problem was setting the vkCmdSetVertexBuffers wrong. vkCmdSetVertexBuffers requires an array of VkDeviceSize[] pOffsets even if you don't use them. I made a typo, writing VkDeviceSize[1] pOffsets = {1} instead of VkDeviceSize[1] = {0}

Youssef
  • 1
  • 1
  • 2