Skip to content

Latest commit

 

History

History
78 lines (59 loc) · 2.65 KB

pnext_and_stype.md

File metadata and controls

78 lines (59 loc) · 2.65 KB

pNext and sType

People new to Vulkan will start to notice the pNext and sType variables all around the Vulkan Spec.

The void* pNext is used to allow for expanding the Vulkan Spec by creating a Linked List between structures. The pNext valid usage section of the Vulkan Spec goes into detail explaining the two different variations of pNext structures. The VkStructureType sType is used by the loader, layers, and implementations to know what type of struct was passed in by pNext. pNext is mostly used when dealing with extensions that expose new structures.

An example to help illustrate the use of pNext from an application's point of view:

// An example with two structures, "a" and "b"
// These structs have members you'd find in real Vulkan structures
typedef struct VkA {
    VkStructureType sType;
    void* pNext;
    uint32_t value;
} VkA;

typedef struct VkB {
    VkStructureType sType;
    void* pNext;
    uint32_t value;
} VkB;

// A Vulkan Function that takes struct "a" as an argument
// This function is in charge of populating the values
void vkGetValue(VkA* pA);

// Define "a" and "b" and set their sType
struct VkB b = {};
b.sType = VK_STRUCTURE_TYPE_B;

struct VkA a = {};
a.sType = VK_STRUCTURE_TYPE_A;

// Set the pNext pointer from "a" to "b"
a.pNext = (void*)&b;

// Pass "a" to the function
vkGetValue(&a);

// Use the values which were both set from vkGetValue()
printf("VkA value = %u \n", a.value);
printf("VkB value = %u \n", b.value);

Underneath, the loader, layers, and driver are now able to find the chained pNext structures. Here is an example to help illustrate how one could implement pNext from the loader, layer, or driver point of view.

void vkGetValue(VkA* pA) {

    VkA* next = reinterpret_cast<VkA*>(pA->pNext);
    while (next != nullptr) {
        switch (next->sType) {

            case VK_STRUCTURE_TYPE_B:
                VkB* pB = reinterpret_cast<VkB*>(next);
                // This is where the "b.value" above got set
                pB->value = 42;
                break;

            case VK_STRUCTURE_TYPE_C:
                // Can chain as many structures as supported
                VkC* pC = reinterpret_cast<VkC*>(next);
                SomeFunction(pC);
                break;

            default:
                LOG("Unsupported sType %d", next->sType);
        }

        // This works because the first two values of all chainable Vulkan structs
        // are "sType" and "pNext" making the offsets the same for pNext
        next = reinterpret_cast<VkA*>(next->pNext);
    }

    // ...
}