]> O.S.I.I.S - jp/vkhelpers.git/commitdiff
first commit
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 8 Dec 2017 14:15:06 +0000 (15:15 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 8 Dec 2017 14:15:06 +0000 (15:15 +0100)
README.md [new file with mode: 0644]
vkh_buffer.c [new file with mode: 0644]
vkh_buffer.h [new file with mode: 0644]
vkh_device.c [new file with mode: 0644]
vkh_device.h [new file with mode: 0644]
vkh_image.c [new file with mode: 0644]
vkh_image.h [new file with mode: 0644]
vkh_presenter.c [new file with mode: 0644]
vkh_presenter.h [new file with mode: 0644]
vkhelpers.c [new file with mode: 0644]
vkhelpers.h [new file with mode: 0644]

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..78db504
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# vkhelpers
diff --git a/vkh_buffer.c b/vkh_buffer.c
new file mode 100644 (file)
index 0000000..8de3025
--- /dev/null
@@ -0,0 +1,47 @@
+#include "vkh_buffer.h"
+#include "vkhelpers.h"
+
+void vkh_buffer_create(vkh_device *pDev, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, vkh_buffer* buff){
+    buff->pDev = pDev;
+    VkBufferCreateInfo bufCreateInfo = {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+        .usage = usage, .size = size, .sharingMode = VK_SHARING_MODE_EXCLUSIVE};
+    VK_CHECK_RESULT(vkCreateBuffer(pDev->vkDev, &bufCreateInfo, NULL, &buff->buffer));
+
+    VkMemoryRequirements memReq;
+    vkGetBufferMemoryRequirements(pDev->vkDev, buff->buffer, &memReq);
+    VkMemoryAllocateInfo memAllocInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+                                          .allocationSize = memReq.size };
+    assert(memory_type_from_properties(&pDev->phyMemProps, memReq.memoryTypeBits,memoryPropertyFlags, &memAllocInfo.memoryTypeIndex));
+    VK_CHECK_RESULT(vkAllocateMemory(pDev->vkDev, &memAllocInfo, NULL, &buff->memory));
+
+    buff->alignment = memReq.alignment;
+    buff->size = memAllocInfo.allocationSize;
+    buff->usageFlags = usage;
+    buff->memoryPropertyFlags = memoryPropertyFlags;
+
+    VK_CHECK_RESULT(vkh_buffer_bind(buff));
+}
+
+void vkh_buffer_destroy(vkh_buffer* buff){
+    if (buff->buffer)
+        vkDestroyBuffer(buff->pDev->vkDev, buff->buffer, NULL);
+    if (buff->memory)
+        vkFreeMemory(buff->pDev->vkDev, buff->memory, NULL);
+}
+
+
+VkResult vkh_buffer_map(vkh_buffer* buff){
+    return vkMapMemory(buff->pDev->vkDev, buff->memory, 0, VK_WHOLE_SIZE, 0, &buff->mapped);
+}
+void vkh_buffer_unmap(vkh_buffer* buff){
+    if (!buff->mapped)
+        return;
+    vkUnmapMemory(buff->pDev->vkDev, buff->memory);
+    buff->mapped = NULL;
+}
+
+VkResult vkh_buffer_bind(vkh_buffer* buff)
+{
+    return vkBindBufferMemory(buff->pDev->vkDev, buff->buffer, buff->memory, 0);
+}
diff --git a/vkh_buffer.h b/vkh_buffer.h
new file mode 100644 (file)
index 0000000..68aa1a1
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef VKH_BUFFER_H
+#define VKH_BUFFER_H
+
+#include <vulkan/vulkan.h>
+#include "vkh_device.h"
+
+typedef struct vkh_buffer_t {
+       vkh_device* pDev;
+       VkBuffer buffer;
+       VkDeviceMemory memory;
+       VkDescriptorBufferInfo descriptor;
+       VkDeviceSize size;
+       VkDeviceSize alignment;
+
+       VkBufferUsageFlags usageFlags;
+       VkMemoryPropertyFlags memoryPropertyFlags;
+
+       void* mapped;
+}vkh_buffer;
+
+void vkh_buffer_create (vkh_device *pDev, VkBufferUsageFlags usage,
+               VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, vkh_buffer* buff);
+void vkh_buffer_destroy (vkh_buffer* buff);
+VkResult vkh_buffer_map (vkh_buffer* buff);
+void vkh_buffer_unmap (vkh_buffer* buff);
+VkResult vkh_buffer_bind (vkh_buffer* buff);
+
+#endif
diff --git a/vkh_device.c b/vkh_device.c
new file mode 100644 (file)
index 0000000..debfffb
--- /dev/null
@@ -0,0 +1 @@
+#include "vkh_device.h"
diff --git a/vkh_device.h b/vkh_device.h
new file mode 100644 (file)
index 0000000..cf36df3
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef VKH_DEVICE_H
+#define VKH_DEVICE_H
+
+#include "vkhelpers.h"
+
+typedef struct vkh_device_t{
+       VkDevice vkDev;
+       VkPhysicalDeviceMemoryProperties phyMemProps;
+       VkRenderPass renderPass;
+}vkh_device;
+
+#endif
diff --git a/vkh_image.c b/vkh_image.c
new file mode 100644 (file)
index 0000000..a0a14e8
--- /dev/null
@@ -0,0 +1,90 @@
+#include "vkh_image.h"
+
+void _vkh_image_create (vkh_device *pDev, VkImageType imageType,
+                  VkFormat format, uint32_t width, uint32_t height,
+                  VkMemoryPropertyFlags memprops, VkImageUsageFlags usage,
+                  VkSampleCountFlagBits samples, VkImageTiling tiling,
+                  uint32_t mipLevels, uint32_t arrayLayers,
+                  VkImageLayout layout, vkh_image* img){
+    img->pDev = pDev;
+    img->width = width;
+    img->height = height;
+
+    VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+                                     .imageType = imageType,
+                                     .tiling = tiling,
+                                     .initialLayout = layout,
+                                     .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+                                     .usage = usage,
+                                     .format = format,
+                                     .extent = {width,height,1},
+                                     .mipLevels = mipLevels,
+                                     .arrayLayers = arrayLayers,
+                                     .samples = samples };
+
+    VK_CHECK_RESULT(vkCreateImage(pDev->vkDev, &image_info, NULL, &img->image));
+
+    img->infos = image_info;
+
+    VkMemoryRequirements memReq;
+    vkGetImageMemoryRequirements(pDev->vkDev, img->image, &memReq);
+    VkMemoryAllocateInfo memAllocInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+                                          .allocationSize = memReq.size };
+    assert(memory_type_from_properties(&pDev->phyMemProps, memReq.memoryTypeBits, memprops,&memAllocInfo.memoryTypeIndex));
+    VK_CHECK_RESULT(vkAllocateMemory(pDev->vkDev, &memAllocInfo, NULL, &img->memory));
+    VK_CHECK_RESULT(vkBindImageMemory(pDev->vkDev, img->image, img->memory, 0));
+}
+void vkh_tex2d_array_create (vkh_device *pDev,
+                             VkFormat format, uint32_t width, uint32_t height, uint32_t layers,
+                             VkMemoryPropertyFlags memprops, VkImageUsageFlags usage, vkh_image* img){
+    _vkh_image_create (pDev, VK_IMAGE_TYPE_2D, format, width, height, memprops,usage,
+        VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, 1, layers, VK_IMAGE_LAYOUT_PREINITIALIZED, img);
+}
+
+void vkh_image_create (vkh_device *pDev,
+                           VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling,
+                           VkMemoryPropertyFlags memprops,
+                           VkImageUsageFlags usage, VkImageLayout layout, vkh_image* img)
+{
+    _vkh_image_create (pDev, VK_IMAGE_TYPE_2D, format, width, height, memprops,usage,
+                      VK_SAMPLE_COUNT_1_BIT, tiling, 1, 1, layout, img);
+}
+void vkh_image_ms_create (vkh_device *pDev,
+                           VkFormat format, VkSampleCountFlagBits num_samples, uint32_t width, uint32_t height,
+                           VkMemoryPropertyFlags memprops,
+                           VkImageUsageFlags usage, VkImageLayout layout, vkh_image* img){
+    _vkh_image_create (pDev, VK_IMAGE_TYPE_2D, format, width, height, memprops,usage,
+                      num_samples, VK_IMAGE_TILING_OPTIMAL, 1, 1, layout, img);
+}
+void vkh_image_create_descriptor(vkh_image* img, VkImageViewType viewType, VkImageAspectFlags aspectFlags, VkFilter magFilter,
+                                 VkFilter minFilter, VkSamplerMipmapMode mipmapMode)
+{
+    img->pDescriptor = (VkDescriptorImageInfo*)malloc(sizeof(VkDescriptorImageInfo));
+    img->pDescriptor->imageLayout = img->infos.initialLayout;
+    VkImageViewCreateInfo viewInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+                                         .image = img->image,
+                                         .viewType = viewType,
+                                         .format = img->infos.format,
+                                         .components = {VK_COMPONENT_SWIZZLE_R,VK_COMPONENT_SWIZZLE_G,VK_COMPONENT_SWIZZLE_B,VK_COMPONENT_SWIZZLE_A},
+                                         .subresourceRange = {aspectFlags,0,1,0,img->infos.arrayLayers}};
+    VK_CHECK_RESULT(vkCreateImageView(img->pDev->vkDev, &viewInfo, NULL, &img->pDescriptor->imageView));
+
+    VkSamplerCreateInfo samplerCreateInfo = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+                                              .maxAnisotropy = 1.0,
+                                              .magFilter = magFilter,
+                                              .minFilter = minFilter,
+                                              .mipmapMode = mipmapMode};
+    VK_CHECK_RESULT(vkCreateSampler(img->pDev->vkDev, &samplerCreateInfo, NULL, &img->pDescriptor->sampler));
+
+}
+void vkh_image_destroy(vkh_image* img)
+{
+    if (img->pDescriptor != NULL){
+        vkDestroyImageView(img->pDev->vkDev,img->pDescriptor->imageView,NULL);
+        if(img->pDescriptor->sampler != VK_NULL_HANDLE)
+            vkDestroySampler(img->pDev->vkDev,img->pDescriptor->sampler,NULL);
+    }
+    free(img->pDescriptor);
+    vkDestroyImage(img->pDev->vkDev,img->image,NULL);
+    vkFreeMemory(img->pDev->vkDev, img->memory, NULL);
+}
diff --git a/vkh_image.h b/vkh_image.h
new file mode 100644 (file)
index 0000000..df87294
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef VKH_IMAGE_H
+#define VKH_IMAGE_H
+
+#include "vkhelpers.h"
+#include "vkh_device.h"
+
+typedef struct vkh_image_t {
+       vkh_device*                             pDev;
+       VkImageCreateInfo               infos;
+       uint32_t                                width, height;
+       VkImage                                 image;
+       VkDeviceMemory                  memory;
+       VkDescriptorImageInfo*  pDescriptor;
+}vkh_image;
+
+void vkh_image_create          (vkh_device* pDev, VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling,
+                                                               VkMemoryPropertyFlags memprops, VkImageUsageFlags usage, VkImageLayout layout, vkh_image *img);
+void vkh_image_ms_create       (vkh_device *pDev, VkFormat format, VkSampleCountFlagBits num_samples, uint32_t width, uint32_t height,
+                                                               VkMemoryPropertyFlags memprops, VkImageUsageFlags usage, VkImageLayout layout, vkh_image *img);
+
+void vkh_tex2d_array_create (vkh_device *pDev, VkFormat format, uint32_t width, uint32_t height, uint32_t layers,
+                                                               VkMemoryPropertyFlags memprops, VkImageUsageFlags usage, vkh_image* img);
+
+void vkh_image_create_descriptor(vkh_image* img, VkImageViewType viewType, VkImageAspectFlags aspectFlags, VkFilter magFilter, VkFilter minFilter,
+                                                                VkSamplerMipmapMode mipmapMode);
+void vkh_image_destroy(vkh_image* img);
+#endif
diff --git a/vkh_presenter.c b/vkh_presenter.c
new file mode 100644 (file)
index 0000000..851812a
--- /dev/null
@@ -0,0 +1,2 @@
+#include "vkh_presenter.h"
+
diff --git a/vkh_presenter.h b/vkh_presenter.h
new file mode 100644 (file)
index 0000000..0a633e2
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef VKH_PRESENTER_H
+#define VKH_PRESENTER_H
+
+#include "vkhelpers.h"
+
+
+
+#endif
diff --git a/vkhelpers.c b/vkhelpers.c
new file mode 100644 (file)
index 0000000..ba3563c
--- /dev/null
@@ -0,0 +1,259 @@
+
+#include "vkhelpers.h"
+
+VkPhysicalDevice vkh_find_phy (VkInstance inst, VkPhysicalDeviceType phyType) {
+    uint32_t gpu_count = 0;
+
+    VK_CHECK_RESULT(vkEnumeratePhysicalDevices (inst, &gpu_count, NULL));
+
+    VkPhysicalDevice phys[gpu_count];
+
+    VK_CHECK_RESULT(vkEnumeratePhysicalDevices (inst, &gpu_count, &phys));
+
+    for (int i=0; i<gpu_count; i++){
+        VkPhysicalDeviceProperties phy;
+        vkGetPhysicalDeviceProperties (phys[i], &phy);
+        if (phy.deviceType & phyType){
+            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];
+        }
+    }
+    fprintf (stderr, "No suitable GPU found\n");
+    exit (-1);
+}
+
+VkFence vkh_fence_create (VkDevice dev) {
+    VkFence fence;
+    VkFenceCreateInfo fenceInfo = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+                                    .pNext = NULL,
+                                    .flags = 0 };
+    VK_CHECK_RESULT(vkCreateFence(dev, &fenceInfo, NULL, &fence));
+    return fence;
+}
+VkSemaphore vkh_semaphore_create (VkDevice dev) {
+    VkSemaphore semaphore;
+    VkSemaphoreCreateInfo info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+                                                           .pNext = NULL,
+                                                           .flags = 0};
+    VK_CHECK_RESULT(vkCreateSemaphore(dev, &info, NULL, &semaphore));
+    return semaphore;
+}
+VkCommandPool vkh_cmd_pool_create (VkDevice dev, uint32_t qFamIndex, VkCommandPoolCreateFlags flags){
+    VkCommandPool cmdPool;
+    VkCommandPoolCreateInfo cmd_pool_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+                                              .pNext = NULL,
+                                              .queueFamilyIndex = qFamIndex,
+                                              .flags = flags };
+    VK_CHECK_RESULT (vkCreateCommandPool(dev, &cmd_pool_info, NULL, &cmdPool));
+    return cmdPool;
+}
+VkCommandBuffer vkh_cmd_buff_create (VkDevice dev, VkCommandPool cmdPool, VkCommandBufferLevel level){
+    VkCommandBuffer cmdBuff;
+    VkCommandBufferAllocateInfo cmd = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+                                        .pNext = NULL,
+                                        .commandPool = cmdPool,
+                                        .level = level,
+                                        .commandBufferCount = 1 };
+    VK_CHECK_RESULT (vkAllocateCommandBuffers (dev, &cmd, &cmdBuff));
+    return cmdBuff;
+}
+
+void vkh_cmd_begin(VkCommandBuffer cmdBuff, VkCommandBufferUsageFlags flags) {
+    VkCommandBufferBeginInfo cmd_buf_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+                                              .pNext = NULL,
+                                              .flags = flags,
+                                              .pInheritanceInfo = NULL };
+
+    VK_CHECK_RESULT (vkBeginCommandBuffer (cmdBuff, &cmd_buf_info));
+}
+void vkh_cmd_end(VkCommandBuffer cmdBuff){
+    VK_CHECK_RESULT (vkEndCommandBuffer (cmdBuff));
+}
+void vkh_cmd_submit(VkQueue queue, VkCommandBuffer *pCmdBuff, VkFence fence){
+    VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+                                 .commandBufferCount = 1,
+                                 .pCommandBuffers = pCmdBuff};
+    VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submit_info, fence));
+}
+void vkh_cmd_submit_with_semaphores(VkQueue queue, VkCommandBuffer *pCmdBuff, VkSemaphore waitSemaphore,
+                                    VkSemaphore signalSemaphore, 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};
+
+    if (waitSemaphore != VK_NULL_HANDLE){
+        submit_info.waitSemaphoreCount = 1;
+        submit_info.pWaitSemaphores = &waitSemaphore;
+    }
+    if (signalSemaphore != VK_NULL_HANDLE){
+        submit_info.signalSemaphoreCount = 1;
+        submit_info.pSignalSemaphores= &signalSemaphore;
+    }
+
+    VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submit_info, fence));
+}
+
+
+
+void set_image_layout(VkCommandBuffer cmdBuff, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout,
+                      VkImageLayout new_image_layout, VkPipelineStageFlags src_stages, VkPipelineStageFlags dest_stages) {
+    VkImageMemoryBarrier image_memory_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                                                  .oldLayout = old_image_layout,
+                                                  .newLayout = new_image_layout,
+                                                  .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                                  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                                  .image = image,
+                                                  .subresourceRange = {aspectMask,0,1,0,1}};
+
+    switch (old_image_layout) {
+        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+            image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+            break;
+
+        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+            image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+            break;
+
+        case VK_IMAGE_LAYOUT_PREINITIALIZED:
+            image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+            break;
+
+        default:
+            break;
+    }
+
+    switch (new_image_layout) {
+        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+            image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+            break;
+
+        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+            image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+            break;
+
+        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+            image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+            break;
+
+        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+            image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+            break;
+
+        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+            image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+            break;
+
+        default:
+            break;
+    }
+
+    vkCmdPipelineBarrier(cmdBuff, src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
+}
+
+bool memory_type_from_properties(VkPhysicalDeviceMemoryProperties* memory_properties, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex) {
+    // Search memtypes to find first index with those properties
+    for (uint32_t i = 0; i < memory_properties->memoryTypeCount; i++) {
+        if ((typeBits & 1) == 1) {
+            // Type is available, does it match user properties?
+            if ((memory_properties->memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
+                *typeIndex = i;
+                return true;
+            }
+        }
+        typeBits >>= 1;
+    }
+    // No memory types matched, return failure
+    return false;
+}
+
+VkShaderModule vkh_load_module(VkDevice dev, const char* path){
+    VkShaderModule module;
+    size_t filelength;
+    char* pCode = read_spv(path, &filelength);
+    VkShaderModuleCreateInfo createInfo = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+                                            .pCode = pCode,
+                                            .codeSize = filelength };
+    VK_CHECK_RESULT(vkCreateShaderModule(dev, &createInfo, NULL, &module));
+    free (pCode);
+    //assert(module != VK_NULL_HANDLE);
+    return module;
+}
+
+char *read_spv(const char *filename, size_t *psize) {
+    long int size;
+    size_t retval;
+    void *shader_code;
+
+#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
+    filename =[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: @(filename)].UTF8String;
+#endif
+
+    FILE *fp = fopen(filename, "rb");
+    if (!fp)
+        return NULL;
+
+    fseek(fp, 0L, SEEK_END);
+    size = ftell(fp);
+
+    fseek(fp, 0L, SEEK_SET);
+
+    shader_code = malloc(size);
+    retval = fread(shader_code, size, 1, fp);
+    assert(retval == 1);
+
+    *psize = size;
+
+    fclose(fp);
+    return shader_code;
+}
+
+// Read file into array of bytes, and cast to uint32_t*, then return.
+// The data has been padded, so that it fits into an array uint32_t.
+uint32_t* readFile(uint32_t* length, const char* filename) {
+
+    FILE* fp = fopen(filename, "rb");
+    if (fp == 0) {
+        printf("Could not find or open file: %s\n", filename);
+    }
+
+    // get file size.
+    fseek(fp, 0, SEEK_END);
+    long filesize = ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+
+    long filesizepadded = (long)(ceil(filesize / 4.0)) * 4;
+
+    // read file contents.
+    char *str = (char*)malloc(filesizepadded*sizeof(char));
+    fread(str, filesize, sizeof(char), fp);
+    fclose(fp);
+
+    // data padding.
+    for (int i = filesize; i < filesizepadded; i++)
+        str[i] = 0;
+
+    *length = filesizepadded;
+    return (uint32_t *)str;
+}
+
+void dumpLayerExts () {
+    printf ("Layers:\n");
+    uint32_t instance_layer_count;
+    assert (vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL)==VK_SUCCESS);
+    if (instance_layer_count == 0)
+        return;
+    VkLayerProperties vk_props[instance_layer_count];
+    assert (vkEnumerateInstanceLayerProperties(&instance_layer_count, vk_props)==VK_SUCCESS);
+
+    for (uint32_t i = 0; i < instance_layer_count; i++) {
+        printf ("\t%s, %s\n", vk_props[i].layerName, vk_props[i].description);
+/*        res = init_global_extension_properties(layer_props);
+        if (res) return res;
+        info.instance_layer_properties.push_back(layer_props);*/
+    }
+}
diff --git a/vkhelpers.h b/vkhelpers.h
new file mode 100644 (file)
index 0000000..d26a688
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef VK_HELPERS_H
+#define VK_HELPERS_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <math.h>
+
+#include <vulkan/vulkan.h>
+
+#define FB_COLOR_FORMAT VK_FORMAT_B8G8R8A8_UNORM
+
+#define VK_CHECK_RESULT(f)                                                                                                                                                             \
+{                                                                                                                                                                                                              \
+    VkResult res = (f);                                                                                                                                                                        \
+    if (res != VK_SUCCESS)                                                                                                                                                             \
+    {                                                                                                                                                                                                  \
+        printf("Fatal : VkResult is %d in %s at line %d\n", res,  __FILE__, __LINE__); \
+        assert(res == VK_SUCCESS);                                                                                                                                             \
+    }                                                                                                                                                                                                  \
+}
+
+VkPhysicalDevice vkh_find_phy (VkInstance inst, VkPhysicalDeviceType phyType);
+VkFence vkh_fence_create (VkDevice dev);
+VkSemaphore vkh_semaphore_create (VkDevice dev);
+VkCommandPool vkh_cmd_pool_create (VkDevice dev, uint32_t qFamIndex, VkCommandPoolCreateFlags flags);
+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,
+                                    VkSemaphore signalSemaphore, VkFence fence);
+void vkcrow_cmd_copy_submit(VkQueue queue, VkCommandBuffer *pCmdBuff, VkSemaphore* pWaitSemaphore, VkSemaphore* pSignalSemaphore);
+
+VkShaderModule vkh_load_module(VkDevice dev, const char* path);
+
+void set_image_layout(VkCommandBuffer cmdBuff, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout,
+                      VkImageLayout new_image_layout, VkPipelineStageFlags src_stages, VkPipelineStageFlags dest_stages);
+
+bool memory_type_from_properties(VkPhysicalDeviceMemoryProperties* memory_properties, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex);
+char *read_spv(const char *filename, size_t *psize);
+uint32_t* readFile(uint32_t* length, const char* filename);
+
+void dumpLayerExts ();
+#endif