This document proposes adding legacy features for vertex attributes as found in OpenGL.

1. Problem Statement

OpenGL allows three features that Vulkan explicitly prohibits:

  • Vertex attributes loaded from arbitrary buffer alignments

  • Vertex attributes using arbitrary strides

  • Vertex attributes where the component data type of the binding does not match the component numeric type of the shader input

This proposal aims to provide this legacy functionality for non-64-bit attributes.

2. Solution Space

These legacy features can be emulated by rewriting vertex buffers and generating shader variants. Neither option is as optimal as having the underlying driver handle the functionality, where it may be a no-op.

3. Proposal

3.1. API Features

The following features are exposed by this extension:

typedef struct VkPhysicalDeviceLegacyVertexAttributesFeaturesEXT {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           legacyVertexAttributes;
} VkPhysicalDeviceLegacyVertexAttributesFeaturesEXT;

legacyVertexAttributes is the core feature enabling this extension’s functionality.

The following properties are exposed by this extension:

typedef struct VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           nativeUnalignedPerformance;
} VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT;

nativeUnalignedPerformance indicates that using unaligned vertex fetches on this implementation will not incur significant performance penalties.

4. Examples

Enabling this feature allows the following example scenarios for a user with dynamic vertex input active:

  • Binding a vertex buffer at offset=7

  • Binding a VK_FORMAT_R32_UINT attribute with stride=1

  • Binding a VK_FORMAT_R8_UINT attribute and reading it as signed int in a shader

5. Issues

5.1. RESOLVED: Should implementations convert float/integer values?

No. When fetching an integer data type from float values or float data types from integer values, the resulting shader values are implementation-dependent.