### What is vkh?
**vkh** is a multiplatform helper library for [Vulkan](https://www.khronos.org/vulkan/) written in **c**.
-
vkh main goal is to offer an api which will ease the development of wrappers for higher level languages.
No additional library except vulkan is required.
#ifndef VK_HELPERS_H
#define VK_HELPERS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
}
typedef struct _vkh_app_t* VkhApp;
+typedef struct _vkh_phy_t* VkhPhyInfo;
typedef struct _vkh_device_t* VkhDevice;
typedef struct _vkh_image_t* VkhImage;
typedef struct _vkh_buffer_t* VkhBuffer;
typedef struct _vkh_queue_t* VkhQueue;
//typedef struct _vkh_presenter_t* VkhPresenter;
-///////////////////
+// VkhApp
VkhApp vkh_app_create (const char* app_name, int ext_count, const char* extentions[]);
void vkh_app_destroy (VkhApp app);
VkInstance vkh_app_get_inst (VkhApp app);
VkPhysicalDevice vkh_app_select_phy (VkhApp app, VkPhysicalDeviceType preferedPhyType);
+VkhPhyInfo* vkh_app_get_phyinfos (VkhApp app, uint32_t* count);
+void vkh_app_free_phyinfos (uint32_t count, VkhPhyInfo* infos);
-///////////////////////////////
+VkPhysicalDeviceProperties vkh_app_get_phy_properties (VkhApp app, uint32_t phyIndex);
+// VkhPhy
+VkhPhyInfo vkh_phyinfo_create (VkhApp app, VkPhysicalDevice phy);
+void vkh_phyinfo_destroy (VkhPhyInfo phy);
+// VkhImage
VkhImage vkh_image_create (VkhDevice pDev, VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling,
VkMemoryPropertyFlags memprops, VkImageUsageFlags usage);
VkhImage vkh_image_ms_create (VkhDevice pDev, VkFormat format, VkSampleCountFlagBits num_samples, uint32_t width, uint32_t height,
VkImageLayout vkh_image_get_layout (VkhImage img);
VkSampler vkh_image_get_sampler (VkhImage img);
VkDescriptorImageInfo vkh_image_get_descriptor(VkhImage img, VkImageLayout imageLayout);
-////////////////////////////////
+// VkhBuffer
VkhBuffer vkh_buffer_create (VkhDevice pDev, VkBufferUsageFlags usage,
VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size);
void vkh_buffer_destroy (VkhBuffer buff);
VkCommandBuffer vkh_cmd_buff_create (VkDevice dev, VkCommandPool cmdPool, VkCommandBufferLevel level);
void vkh_cmd_begin (VkCommandBuffer cmdBuff, VkCommandBufferUsageFlags flags);
void vkh_cmd_end (VkCommandBuffer cmdBuff);
-void vkh_cmd_submit (VkQueue queue, VkCommandBuffer *pCmdBuff, VkFence fence);
-void vkh_cmd_submit_with_semaphores(VkQueue queue, VkCommandBuffer *pCmdBuff, VkSemaphore waitSemaphore,
+void vkh_cmd_submit (VkhQueue queue, VkCommandBuffer *pCmdBuff, VkFence fence);
+void vkh_cmd_submit_with_semaphores(VkhQueue queue, VkCommandBuffer *pCmdBuff, VkSemaphore waitSemaphore,
VkSemaphore signalSemaphore, VkFence fence);
VkShaderModule vkh_load_module(VkDevice dev, const char* path);
void vkh_queue_destroy (VkhQueue queue);
VkhQueue vkh_queue_find (VkhDevice dev, VkQueueFlags flags);
/////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
.ppEnabledLayerNames = enabledLayers };
VK_CHECK_RESULT(vkCreateInstance (&inst_info, NULL, &app->inst));
-
- VK_CHECK_RESULT(vkEnumeratePhysicalDevices (app->inst, &app->phyCount, NULL));
-
return app;
}
return app->inst;
}
-VkPhysicalDevice vkh_app_select_phy (VkhApp app, VkPhysicalDeviceType preferedPhyType) {
- VkPhysicalDevice phys[app->phyCount];
- VK_CHECK_RESULT(vkEnumeratePhysicalDevices (app->inst, &app->phyCount, &phys));
+VkhPhyInfo* vkh_app_get_phyinfos (VkhApp app, uint32_t* count) {
+ VK_CHECK_RESULT(vkEnumeratePhysicalDevices (app->inst, count, NULL));
+ VkPhysicalDevice phyDevices[(*count)];
+ VK_CHECK_RESULT(vkEnumeratePhysicalDevices (app->inst, count, phyDevices));
+ VkhPhyInfo* infos = (VkhPhyInfo*)malloc((*count) * sizeof(VkhPhyInfo));
+
+ for (int i=0; i<(*count); i++)
+ infos[i] = vkh_phyinfo_create (app, phyDevices[i]);
+
+ return infos;
+}
- if (app->phyCount == 1)
- return phys[0];
+void vkh_app_free_phyinfos (uint32_t count, VkhPhyInfo* infos) {
+ for (int i=0; i<count; i++)
+ vkh_phyinfo_destroy (infos[i]);
+ free (infos);
+}
+
+
+VkPhysicalDevice vkh_app_select_phy (VkhApp app, VkPhysicalDeviceType preferedPhyType) {
+ /*if (app->phyCount == 1)
+ return app->phyDevices[0];
for (int i=0; i<app->phyCount; i++){
VkPhysicalDeviceProperties phy;
- vkGetPhysicalDeviceProperties (phys[i], &phy);
+ vkGetPhysicalDeviceProperties (app->phyDevices[i], &phy);
if (phy.deviceType & preferedPhyType){
+#if DEBUG
printf ("GPU: %s vulkan:%d.%d.%d driver:%d\n", phy.deviceName,
phy.apiVersion>>22, phy.apiVersion>>12&2048, phy.apiVersion&8191,
phy.driverVersion);
- return phys[i];
+#endif
+ return app->phyDevices[i];
}
}
fprintf (stderr, "No suitable GPU found\n");
- exit (-1);
+ exit (-1);*/
}
typedef struct _vkh_app_t{
VkApplicationInfo infos;
VkInstance inst;
- uint32_t phyCount;
}vkh_app_t;
#endif
#include "vkh_device.h"
+
--- /dev/null
+#include "vkh_phyinfo.h"
+#include "vkh_app.h"
+
+
+VkhPhyInfo vkh_phyinfo_create (VkhApp app, VkPhysicalDevice phy) {
+ VkhPhyInfo pi = (vkh_phy_t*)calloc(1, sizeof(vkh_phy_t));
+ pi->phy = phy;
+
+ vkGetPhysicalDeviceProperties (phy, &pi->properties);
+ vkGetPhysicalDeviceMemoryProperties (phy, &pi->memProps);
+
+ vkGetPhysicalDeviceQueueFamilyProperties (phy, &pi->queueCount, NULL);
+ pi->queues = (VkQueueFamilyProperties*)malloc(pi->queueCount * sizeof(VkQueueFamilyProperties));
+ vkGetPhysicalDeviceQueueFamilyProperties (phy, &pi->queueCount, pi->queues);
+
+ //identify dedicated queues
+
+ //try to find dedicated queues
+ pi->cQueue = -1;
+ pi->gQueue = -1;
+ pi->tQueue = -1;
+
+ for (int j=0; j<pi->queueCount; j++){
+ switch (pi->queues[j].queueFlags) {
+ case VK_QUEUE_GRAPHICS_BIT:
+ if (pi->gQueue<0)
+ pi->gQueue = j;
+ break;
+ case VK_QUEUE_COMPUTE_BIT:
+ if (pi->cQueue<0)
+ pi->cQueue = j;
+ break;
+ case VK_QUEUE_TRANSFER_BIT:
+ if (pi->tQueue<0)
+ pi->tQueue = j;
+ break;
+ }
+ }
+ //try to find suitable queue if no dedicated one found
+ for (int j=0; j<pi->queueCount; j++){
+ if ((pi->queues[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) && (pi->gQueue < 0))
+ pi->gQueue = j;
+ if ((pi->queues[j].queueFlags & VK_QUEUE_COMPUTE_BIT) && (pi->cQueue < 0))
+ pi->cQueue = j;
+ if ((pi->queues[j].queueFlags & VK_QUEUE_TRANSFER_BIT) && (pi->tQueue < 0))
+ pi->tQueue = j;
+ }
+
+ return pi;
+}
+
+void vkh_phyinfo_destroy (VkhPhyInfo phy) {
+
+ free(phy->queues);
+ free(phy);
+}
+
+void vkh_phyinfo_select_queue (VkhPhyInfo phy, uint32_t qIndex, float* priorities) {
+
+}
--- /dev/null
+#ifndef VKH_PHY_H
+#define VKH_PHY_H
+
+#include "vkh.h"
+
+typedef struct _vkh_phy_t{
+ VkPhysicalDevice phy;
+ VkPhysicalDeviceMemoryProperties memProps;
+ VkPhysicalDeviceProperties properties;
+ VkQueueFamilyProperties* queues;
+ uint32_t queueCount;
+ int cQueue;
+ int gQueue;
+ int tQueue;
+
+ uint32_t qCreateInfosCount;
+ VkDeviceQueueCreateInfo* qCreateInfos;
+}vkh_phy_t;
+#endif
-
+#include "vkh_queue.h"
#include "vkh.h"
VkFence vkh_fence_create (VkDevice dev) {
void vkh_cmd_end(VkCommandBuffer cmdBuff){
VK_CHECK_RESULT (vkEndCommandBuffer (cmdBuff));
}
-void vkh_cmd_submit(VkQueue queue, VkCommandBuffer *pCmdBuff, VkFence fence){
+void vkh_cmd_submit(VkhQueue queue, VkCommandBuffer *pCmdBuff, VkFence fence){
+ VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .pWaitDstStageMask = &stageFlags,
.commandBufferCount = 1,
.pCommandBuffers = pCmdBuff};
- VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submit_info, fence));
+ VK_CHECK_RESULT(vkQueueSubmit(queue->queue, 1, &submit_info, fence));
}
-void vkh_cmd_submit_with_semaphores(VkQueue queue, VkCommandBuffer *pCmdBuff, VkSemaphore waitSemaphore,
+void vkh_cmd_submit_with_semaphores(VkhQueue queue, VkCommandBuffer *pCmdBuff, VkSemaphore waitSemaphore,
VkSemaphore signalSemaphore, VkFence fence){
VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
submit_info.pSignalSemaphores= &signalSemaphore;
}
- VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submit_info, fence));
+ VK_CHECK_RESULT(vkQueueSubmit(queue->queue, 1, &submit_info, fence));
}