aboutsummaryrefslogtreecommitdiff
path: root/src/codec_query/vulkan.c
blob: c19c4f75e34a8436daa76eef23f9121e9bd4a8fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "../../include/codec_query/vulkan.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xf86drm.h>
#include <vulkan/vulkan.h>

#define MAX_PHYSICAL_DEVICES 32

static const char *required_device_extensions[] = {
    "VK_KHR_external_memory_fd",
    "VK_KHR_external_semaphore_fd",
    "VK_KHR_video_encode_queue",
    "VK_KHR_video_queue",
    "VK_KHR_video_maintenance1",
    "VK_EXT_external_memory_dma_buf",
    "VK_EXT_external_memory_host",
    "VK_EXT_image_drm_format_modifier"
};
static int num_required_device_extensions = 8;

bool gsr_get_supported_video_codecs_vulkan(gsr_supported_video_codecs *video_codecs, const char *card_path, bool cleanup) {
    memset(video_codecs, 0, sizeof(*video_codecs));
#if 0
    bool success = false;
    VkInstance instance = NULL;
    VkPhysicalDevice physical_devices[MAX_PHYSICAL_DEVICES];
    VkDevice device = NULL;
    VkExtensionProperties *device_extensions = NULL;

    const VkApplicationInfo app_info = {
        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
        .pApplicationName = "GPU Screen Recorder",
        .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
        .pEngineName = "GPU Screen Recorder",
        .engineVersion = VK_MAKE_VERSION(1, 0, 0),
        .apiVersion = VK_API_VERSION_1_3,
    };

    const VkInstanceCreateInfo instance_create_info = {
        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
        .pApplicationInfo = &app_info
    };

    if(vkCreateInstance(&instance_create_info, NULL, &instance) != VK_SUCCESS) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: vkCreateInstance failed\n");
        goto done;
    }

    uint32_t num_devices = 0;
    if(vkEnumeratePhysicalDevices(instance, &num_devices, NULL) != VK_SUCCESS) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: vkEnumeratePhysicalDevices (query num devices) failed\n");
        goto done;
    }

    if(num_devices == 0) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: no vulkan capable device found\n");
        goto done;
    }

    if(num_devices > MAX_PHYSICAL_DEVICES)
        num_devices = MAX_PHYSICAL_DEVICES;
    
    if(vkEnumeratePhysicalDevices(instance, &num_devices, physical_devices) != VK_SUCCESS) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: vkEnumeratePhysicalDevices (get data) failed\n");
        goto done;
    }

    VkPhysicalDevice physical_device = NULL;
    char device_card_path[128];
    for(uint32_t i = 0; i < num_devices; ++i) {
        VkPhysicalDeviceDrmPropertiesEXT device_drm_properties = {
            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT
        };

        VkPhysicalDeviceProperties2 device_properties = {
            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
            .pNext = &device_drm_properties
        };
        vkGetPhysicalDeviceProperties2(physical_devices[i], &device_properties);

        if(!device_drm_properties.hasPrimary)
            continue;

        snprintf(device_card_path, sizeof(device_card_path), DRM_DEV_NAME, DRM_DIR_NAME, (int)device_drm_properties.primaryMinor);
        if(strcmp(device_card_path, card_path) == 0) {
            physical_device = physical_devices[i];
            break;
        }
    }

    if(!physical_device) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: failed to find a vulkan device that matches opengl device %s\n", card_path);
        goto done;
    }

    const VkDeviceCreateInfo device_create_info = {
        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
        .enabledExtensionCount = num_required_device_extensions,
        .ppEnabledExtensionNames = required_device_extensions
    };

    if(vkCreateDevice(physical_device, &device_create_info, NULL, &device) != VK_SUCCESS) {
        //fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: vkCreateDevice failed. Device %s likely doesn't support vulkan video encoding\n", card_path);
        goto done;
    }

    uint32_t num_device_extensions = 0;
    if(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &num_device_extensions, NULL) != VK_SUCCESS) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: vkEnumerateDeviceExtensionProperties (query num device extensions) failed\n");
        goto done;
    }

    device_extensions = calloc(num_device_extensions, sizeof(VkExtensionProperties));
    if(!device_extensions) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: failed to allocate %d device extensions\n", num_device_extensions);
        goto done;
    }

    if(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &num_device_extensions, device_extensions) != VK_SUCCESS) {
        fprintf(stderr, "gsr error: gsr_get_supported_video_codecs_vulkan: vkEnumerateDeviceExtensionProperties (get data) failed\n");
        goto done;
    }

    for(uint32_t i = 0; i < num_device_extensions; ++i) {
        if(strcmp(device_extensions[i].extensionName, "VK_KHR_video_encode_h264") == 0) {
            video_codecs->h264 = true;
        } else if(strcmp(device_extensions[i].extensionName, "VK_KHR_video_encode_h265") == 0) {
            // TODO: Verify if 10bit and hdr are actually supported
            video_codecs->hevc = true;
            video_codecs->hevc_10bit = true;
            video_codecs->hevc_hdr = true;
        }
    }

    success = true;

    done:
    if(cleanup) {
        if(device)
            vkDestroyDevice(device, NULL);
        if(instance)
            vkDestroyInstance(instance, NULL);
    }
    if(device_extensions)
        free(device_extensions);
    return success;
#else
    video_codecs->h264 = true;
    return true;
#endif
}