vulkan_test2

diff src/vku.c @ 3:68e1c437343f

more vulkan
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 22 Sep 2017 01:01:10 +0300
parents
children c31c4115d44a
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/vku.c	Fri Sep 22 01:01:10 2017 +0300
     1.3 @@ -0,0 +1,281 @@
     1.4 +#include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6 +#include <string.h>
     1.7 +#include <alloca.h>
     1.8 +#include "vku.h"
     1.9 +
    1.10 +static const char *get_device_name(VkPhysicalDeviceType type);
    1.11 +static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags);
    1.12 +static const char *get_queue_flag_string(VkQueueFlagBits flags);
    1.13 +static int ver_major(uint32_t ver);
    1.14 +static int ver_minor(uint32_t ver);
    1.15 +static int ver_patch(uint32_t ver);
    1.16 +static const char *mem_size_str(long sz);
    1.17 +
    1.18 +
    1.19 +VkInstance vk;
    1.20 +VkDevice vkdev;
    1.21 +VkQueue vkq;
    1.22 +
    1.23 +int vku_create_dev(void)
    1.24 +{
    1.25 +	int i, j;
    1.26 +	VkInstanceCreateInfo inst_info;
    1.27 +	VkPhysicalDevice *devices;
    1.28 +	VkDeviceCreateInfo dev_info;
    1.29 +	VkDeviceQueueCreateInfo queue_info;
    1.30 +	VkCommandPoolCreateInfo cmdpool_info;
    1.31 +	uint32_t num_devices;
    1.32 +	int sel_dev = -1;
    1.33 +	int sel_qfamily = -1;
    1.34 +	float qprio = 0.0f;
    1.35 +
    1.36 +	memset(&inst_info, 0, sizeof inst_info);
    1.37 +	inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    1.38 +
    1.39 +	if(vkCreateInstance(&inst_info, 0, &vk) != 0) {
    1.40 +		fprintf(stderr, "failed to create vulkan instance\n");
    1.41 +		return -1;
    1.42 +	}
    1.43 +	printf("created vulkan instance\n");
    1.44 +
    1.45 +	if(vkEnumeratePhysicalDevices(vk, &num_devices, 0) != 0) {
    1.46 +		fprintf(stderr, "failed to enumerate vulkan physical devices\n");
    1.47 +		return -1;
    1.48 +	}
    1.49 +	devices = alloca(num_devices * sizeof *devices);
    1.50 +	if(vkEnumeratePhysicalDevices(vk, &num_devices, devices) != 0) {
    1.51 +		fprintf(stderr, "failed to enumerate vulkan physical devices\n");
    1.52 +		return -1;
    1.53 +	}
    1.54 +	printf("found %u physical device(s)\n", (unsigned int)num_devices);
    1.55 +
    1.56 +	for(i=0; i<(int)num_devices; i++) {
    1.57 +		VkPhysicalDeviceProperties dev_prop;
    1.58 +		VkPhysicalDeviceMemoryProperties mem_prop;
    1.59 +		VkQueueFamilyProperties *qprop;
    1.60 +		uint32_t qprop_count;
    1.61 +
    1.62 +		vkGetPhysicalDeviceProperties(devices[i], &dev_prop);
    1.63 +
    1.64 +		printf("Device %d: %s\n", i, dev_prop.deviceName);
    1.65 +		printf("  type: %s\n", get_device_name(dev_prop.deviceType));
    1.66 +		printf("  API version: %d.%d.%d\n", ver_major(dev_prop.apiVersion), ver_minor(dev_prop.apiVersion),
    1.67 +				ver_patch(dev_prop.apiVersion));
    1.68 +		printf("  driver version: %d.%d.%d\n", ver_major(dev_prop.driverVersion), ver_minor(dev_prop.driverVersion),
    1.69 +				ver_patch(dev_prop.driverVersion));
    1.70 +		printf("  vendor id: %x  device id: %x\n", dev_prop.vendorID, dev_prop.deviceID);
    1.71 +
    1.72 +
    1.73 +		vkGetPhysicalDeviceMemoryProperties(devices[i], &mem_prop);
    1.74 +		printf("  %d memory heaps:\n", mem_prop.memoryHeapCount);
    1.75 +		for(j=0; j<mem_prop.memoryHeapCount; j++) {
    1.76 +			VkMemoryHeap heap = mem_prop.memoryHeaps[j];
    1.77 +			printf("    Heap %d - size: %s, flags: %s\n", j, mem_size_str(heap.size),
    1.78 +					heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ? "device-local" : "-");
    1.79 +		}
    1.80 +		printf("  %d memory types:\n", mem_prop.memoryTypeCount);
    1.81 +		for(j=0; j<mem_prop.memoryTypeCount; j++) {
    1.82 +			VkMemoryType type = mem_prop.memoryTypes[j];
    1.83 +			printf("    Type %d - heap: %d, flags: %s\n", j, type.heapIndex,
    1.84 +					get_mem_prop_flag_string(type.propertyFlags));
    1.85 +		}
    1.86 +
    1.87 +		vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &qprop_count, 0);
    1.88 +		if(qprop_count <= 0) {
    1.89 +			continue;
    1.90 +		}
    1.91 +		qprop = malloc(qprop_count * sizeof *qprop);
    1.92 +		vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &qprop_count, qprop);
    1.93 +
    1.94 +		for(j=0; j<qprop_count; j++) {
    1.95 +			printf("  Queue family %d:\n", j);
    1.96 +			printf("    flags: %s\n", get_queue_flag_string(qprop[j].queueFlags));
    1.97 +			printf("    num queues: %u\n", qprop[j].queueCount);
    1.98 +
    1.99 +			if(qprop[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
   1.100 +				sel_dev = i;
   1.101 +				sel_qfamily = j;
   1.102 +			}
   1.103 +		}
   1.104 +		free(qprop);
   1.105 +	}
   1.106 +
   1.107 +	if(sel_dev < 0 || sel_qfamily < 0) {
   1.108 +		fprintf(stderr, "failed to find any device with a graphics-capable command queue\n");
   1.109 +		vkDestroyDevice(vkdev, 0);
   1.110 +		return -1;
   1.111 +	}
   1.112 +
   1.113 +	/* create device & command queue */
   1.114 +	memset(&queue_info, 0, sizeof queue_info);
   1.115 +	queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
   1.116 +	queue_info.queueFamilyIndex = sel_qfamily;
   1.117 +	queue_info.queueCount = 1;
   1.118 +	queue_info.pQueuePriorities = &qprio;
   1.119 +
   1.120 +	memset(&dev_info, 0, sizeof dev_info);
   1.121 +	dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
   1.122 +	dev_info.queueCreateInfoCount = 1;
   1.123 +	dev_info.pQueueCreateInfos = &queue_info;
   1.124 +
   1.125 +	if(vkCreateDevice(devices[sel_dev], &dev_info, 0, &vkdev) != 0) {
   1.126 +		fprintf(stderr, "failed to create device %d\n", sel_dev);
   1.127 +		return -1;
   1.128 +	}
   1.129 +	printf("created device %d\n", sel_dev);
   1.130 +
   1.131 +	vkGetDeviceQueue(vkdev, sel_qfamily, 0, &vkq);
   1.132 +
   1.133 +	/* create command buffer pool */
   1.134 +	memset(&cmdpool_info, 0, sizeof cmdpool_info);
   1.135 +	cmdpool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
   1.136 +	cmdpool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
   1.137 +	cmdpool_info.queueFamilyIndex = sel_qfamily;
   1.138 +
   1.139 +	if(vkCreateCommandPool(vkdev, &cmdpool_info, 0, &vkcmdpool) != 0) {
   1.140 +		fprintf(stderr, "failed to get command quque!\n");
   1.141 +		return -1;
   1.142 +	}
   1.143 +
   1.144 +	return 0;
   1.145 +}
   1.146 +
   1.147 +void vku_cleanup(void)
   1.148 +{
   1.149 +	if(vk) {
   1.150 +		vkDeviceWaitIdle(vkdev);
   1.151 +		vkDestroyDevice(vkdev, 0);
   1.152 +		vkDestroyInstance(vk, 0);
   1.153 +		vk = 0;
   1.154 +	}
   1.155 +}
   1.156 +
   1.157 +struct vk_buffer *vku_create_buffer(int sz, unsigned int usage)
   1.158 +{
   1.159 +	struct vk_buffer *buf;
   1.160 +	VkBufferCreateInfo binfo;
   1.161 +
   1.162 +	if(!(buf = malloc(sizeof *buf))) {
   1.163 +		perror("failed to allocate vk_buffer structure");
   1.164 +		return 0;
   1.165 +	}
   1.166 +
   1.167 +	memset(&binfo, 0, sizeof binfo);
   1.168 +	binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
   1.169 +	binfo.size = sz;
   1.170 +	binfo.usage = usage;
   1.171 +	binfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
   1.172 +
   1.173 +	if(vkCreateBuffer(vkdev, &binfo, 0, &buf->buf) != 0) {
   1.174 +		fprintf(stderr, "failed to create %d byte buffer (usage: %x)\n", sz, usage);
   1.175 +		return 0;
   1.176 +	}
   1.177 +	// TODO back with memory
   1.178 +	return buf;
   1.179 +}
   1.180 +
   1.181 +void vku_destroy_buffer(struct vk_buffer *buf)
   1.182 +{
   1.183 +	if(buf) {
   1.184 +		vkDestroyBuffer(vkdev, buf->buf, 0);
   1.185 +		free(buf);
   1.186 +	}
   1.187 +}
   1.188 +
   1.189 +static const char *get_device_name(VkPhysicalDeviceType type)
   1.190 +{
   1.191 +	switch(type) {
   1.192 +	case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
   1.193 +		return "integrated GPU";
   1.194 +	case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
   1.195 +		return "discrete GPU";
   1.196 +	case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
   1.197 +		return "virtual GPU";
   1.198 +	case VK_PHYSICAL_DEVICE_TYPE_CPU:
   1.199 +		return "CPU";
   1.200 +	default:
   1.201 +		break;
   1.202 +	}
   1.203 +	return "unknown";
   1.204 +}
   1.205 +
   1.206 +static const char *get_mem_prop_flag_string(VkMemoryPropertyFlags flags)
   1.207 +{
   1.208 +	static char str[128];
   1.209 +
   1.210 +	str[0] = 0;
   1.211 +	if(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
   1.212 +		strcat(str, "device-local ");
   1.213 +	}
   1.214 +	if(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
   1.215 +		strcat(str, "host-visible ");
   1.216 +	}
   1.217 +	if(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
   1.218 +		strcat(str, "host-coherent ");
   1.219 +	}
   1.220 +	if(flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
   1.221 +		strcat(str, "host-cached ");
   1.222 +	}
   1.223 +	if(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
   1.224 +		strcat(str, "lazily-allocated ");
   1.225 +	}
   1.226 +
   1.227 +	if(!*str) {
   1.228 +		strcat(str, "-");
   1.229 +	}
   1.230 +	return str;
   1.231 +}
   1.232 +
   1.233 +static const char *get_queue_flag_string(VkQueueFlagBits flags)
   1.234 +{
   1.235 +	static char str[128];
   1.236 +
   1.237 +	str[0] = 0;
   1.238 +	if(flags & VK_QUEUE_GRAPHICS_BIT) {
   1.239 +		strcat(str, "graphics ");
   1.240 +	}
   1.241 +	if(flags & VK_QUEUE_COMPUTE_BIT) {
   1.242 +		strcat(str, "compute ");
   1.243 +	}
   1.244 +	if(flags & VK_QUEUE_TRANSFER_BIT) {
   1.245 +		strcat(str, "transfer ");
   1.246 +	}
   1.247 +	if(flags & VK_QUEUE_SPARSE_BINDING_BIT) {
   1.248 +		strcat(str, "sparse-binding ");
   1.249 +	}
   1.250 +	if(!*str) {
   1.251 +		strcat(str, "-");
   1.252 +	}
   1.253 +	return str;
   1.254 +}
   1.255 +
   1.256 +static int ver_major(uint32_t ver)
   1.257 +{
   1.258 +	return (ver >> 22) & 0x3ff;
   1.259 +}
   1.260 +
   1.261 +static int ver_minor(uint32_t ver)
   1.262 +{
   1.263 +	return (ver >> 12) & 0x3ff;
   1.264 +}
   1.265 +
   1.266 +static int ver_patch(uint32_t ver)
   1.267 +{
   1.268 +	return ver & 0xfff;
   1.269 +}
   1.270 +
   1.271 +static const char *mem_size_str(long sz)
   1.272 +{
   1.273 +	static char str[64];
   1.274 +	static const char *unitstr[] = { "bytes", "KB", "MB", "GB", "TB", "PB", 0 };
   1.275 +	int uidx = 0;
   1.276 +	sz *= 10;
   1.277 +
   1.278 +	while(sz >= 10240 && unitstr[uidx + 1]) {
   1.279 +		sz /= 1024;
   1.280 +		++uidx;
   1.281 +	}
   1.282 +	sprintf(str, "%ld.%ld %s", sz / 10, sz % 10, unitstr[uidx]);
   1.283 +	return str;
   1.284 +}