typedef struct _vkh_image_t* VkhImage;
typedef struct _vkh_buffer_t* VkhBuffer;
typedef struct _vkh_queue_t* VkhQueue;
-//typedef struct _vkh_presenter_t* VkhPresenter;
+typedef struct _vkh_presenter_t* VkhPresenter;
-// VkhApp
+/*************
+ * 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);
VkPhysicalDeviceProperties vkh_app_get_phy_properties (VkhApp app, uint32_t phyIndex);
// VkhPhy
-VkhPhyInfo vkh_phyinfo_create (VkhApp app, VkPhysicalDevice phy, VkSurfaceKHR surface);
+VkhPhyInfo vkh_phyinfo_create (VkPhysicalDevice phy, VkSurfaceKHR surface);
void vkh_phyinfo_destroy (VkhPhyInfo phy);
-// VkhDevice
+
+/*************
+ * VkhDevice *
+ *************/
VkhDevice vkh_device_create (VkPhysicalDevice phy, VkDevice vkDev);
void vkh_device_destroy (VkhDevice dev);
-// VkhImage
+
+/****************
+ * VkhPresenter *
+ ****************/
+VkhPresenter vkh_presenter_create (VkhDevice dev, uint32_t presentQueueFamIdx, VkSurfaceKHR surface,
+ uint32_t width, uint32_t height,
+ VkFormat preferedFormat, VkPresentModeKHR presentMode);
+void vkh_presenter_destroy (VkhPresenter r);
+bool vkh_presenter_draw (VkhPresenter r);
+void vkh_presenter_build_blit_cmd (VkhPresenter r, VkImage blitSource);
+/************
+ * VkhImage *
+ ************/
+VkhImage vkh_image_import (VkhDevice pDev, VkImage vkImg, VkFormat format, uint32_t width, uint32_t height);
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 *
+ *************/
VkhBuffer vkh_buffer_create (VkhDevice pDev, VkBufferUsageFlags usage,
VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size);
void vkh_buffer_destroy (VkhBuffer buff);
VkBuffer vkh_buffer_get_vkbuffer (VkhBuffer buff);
void* vkh_buffer_get_mapped_pointer (VkhBuffer buff);
-///////////////////////////////
-VkFence vkh_fence_create (VkDevice dev);
-VkFence vkh_fence_create_signaled (VkDevice dev);
-VkSemaphore vkh_semaphore_create (VkDevice dev);
+VkFence vkh_fence_create (VkhDevice dev);
+VkFence vkh_fence_create_signaled (VkhDevice dev);
+VkSemaphore vkh_semaphore_create (VkhDevice dev);
-VkCommandPool vkh_cmd_pool_create (VkDevice dev, uint32_t qFamIndex, VkCommandPoolCreateFlags flags);
-VkCommandBuffer vkh_cmd_buff_create (VkDevice dev, VkCommandPool cmdPool, VkCommandBufferLevel level);
+VkCommandPool vkh_cmd_pool_create (VkhDevice dev, uint32_t qFamIndex, VkCommandPoolCreateFlags flags);
+VkCommandBuffer vkh_cmd_buff_create (VkhDevice dev, VkCommandPool cmdPool, VkCommandBufferLevel level);
void vkh_cmd_begin (VkCommandBuffer cmdBuff, VkCommandBufferUsageFlags flags);
void vkh_cmd_end (VkCommandBuffer cmdBuff);
void vkh_cmd_submit (VkhQueue queue, VkCommandBuffer *pCmdBuff, VkFence fence);
/////////////////////
VkhQueue vkh_queue_create (VkhDevice dev, uint32_t familyIndex, uint32_t qIndex, VkQueueFlags flags);
void vkh_queue_destroy (VkhQueue queue);
-VkhQueue vkh_queue_find (VkhDevice dev, VkQueueFlags flags);
+//VkhQueue vkh_queue_find (VkhDevice dev, VkQueueFlags flags);
/////////////////////
#ifdef __cplusplus
* THE SOFTWARE.
*/
#include "vkh_presenter.h"
+#include "vkh_device.h"
+#include "vkh_image.h"
+void _swapchain_create (VkhPresenter r);
+void _swapchain_destroy (VkhPresenter r);
+void _init_phy_surface (VkhPresenter r, VkFormat preferedFormat, VkPresentModeKHR presentMode);
+
+VkhPresenter vkh_presenter_create (VkhDevice dev, uint32_t presentQueueFamIdx, VkSurfaceKHR surface, uint32_t width, uint32_t height,
+ VkFormat preferedFormat, VkPresentModeKHR presentMode) {
+ VkhPresenter r = (VkhPresenter)calloc(1,sizeof(vkh_presenter_t));
+
+ r->dev = dev;
+ r->qFam = presentQueueFamIdx ;
+ r->surface = surface;
+ r->width = width;
+ r->height = height;
+ vkGetDeviceQueue(r->dev->dev, r->qFam, 0, &r->queue);
+
+ r->cmdPool = vkh_cmd_pool_create (r->dev, presentQueueFamIdx, 0);
+ r->semaPresentEnd = vkh_semaphore_create (r->dev);
+ r->semaDrawEnd = vkh_semaphore_create (r->dev);
+
+ _init_phy_surface (r, preferedFormat, presentMode);
+
+ _swapchain_create (r);
+
+ return r;
+}
+
+void vkh_presenter_destroy (VkhPresenter r) {
+ vkDeviceWaitIdle (r->dev->dev);
+
+ _swapchain_destroy (r);
+
+ vkDestroySemaphore (r->dev->dev, r->semaDrawEnd, NULL);
+ vkDestroySemaphore (r->dev->dev, r->semaPresentEnd, NULL);
+ vkDestroyCommandPool(r->dev->dev, r->cmdPool, NULL);
+
+ free (r);
+}
+
+bool vkh_presenter_draw (VkhPresenter r) {
+
+ // Get the index of the next available swapchain image:
+ VkResult err = vkAcquireNextImageKHR
+ (r->dev->dev, r->swapChain, UINT64_MAX, r->semaPresentEnd, VK_NULL_HANDLE, &r->currentScBufferIndex);
+ if ((err == VK_ERROR_OUT_OF_DATE_KHR) || (err == VK_SUBOPTIMAL_KHR)){
+ _swapchain_create (r);
+ return false;
+
+ }
+
+ VK_CHECK_RESULT(err);
+
+ VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .commandBufferCount = 1,
+ .signalSemaphoreCount = 1,
+ .pSignalSemaphores = &r->semaDrawEnd,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &r->semaPresentEnd,
+ .pWaitDstStageMask = &dstStageMask,
+ .pCommandBuffers = &r->cmdBuffs[r->currentScBufferIndex]};
+ VK_CHECK_RESULT(vkQueueSubmit(r->queue, 1, &submit_info, NULL));
+
+ /* Now present the image in the window */
+ VkPresentInfoKHR present = { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .swapchainCount = 1,
+ .pSwapchains = &r->swapChain,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &r->semaDrawEnd,
+ .pImageIndices = &r->currentScBufferIndex };
+
+ /* Make sure command buffer is finished before presenting */
+ VK_CHECK_RESULT(vkQueuePresentKHR(r->queue, &present));
+ return true;
+}
+
+void vkh_presenter_build_blit_cmd (VkhPresenter r, VkImage blitSource){
+
+ for (int32_t i = 0; i < r->imgCount; ++i)
+ {
+ VkImage bltDstImage = r->ScBuffers[i]->image;
+ VkCommandBuffer cb = r->cmdBuffs[i];
+
+ vkh_cmd_begin(cb,VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT);
+
+ set_image_layout(cb, bltDstImage, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ set_image_layout(cb, blitSource, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageCopy cregion = { .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
+ .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
+ .srcOffset = {},
+ .dstOffset = {0,0,0},
+ .extent = {1024,800,1}};
+
+ vkCmdCopyImage(cb, blitSource, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bltDstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1, &cregion);
+
+ set_image_layout(cb, bltDstImage, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
+
+ vkh_cmd_end(cb);
+ }
+}
+
+void _init_phy_surface(VkhPresenter r, VkFormat preferedFormat, VkPresentModeKHR presentMode){
+ uint32_t count;
+ VK_CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR (r->dev->phy, r->surface, &count, NULL));
+ assert (count>0);
+ VkSurfaceFormatKHR formats[count];
+ VK_CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR (r->dev->phy, r->surface, &count, formats));
+
+ for (int i=0; i<count; i++){
+ if (formats[i].format == preferedFormat) {
+ r->format = formats[i].format;
+ r->colorSpace = formats[i].colorSpace;
+ break;
+ }
+ }
+ assert (r->format != VK_FORMAT_UNDEFINED);
+
+ VK_CHECK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(r->dev->phy, r->surface, &count, NULL));
+ assert (count>0);
+ VkPresentModeKHR presentModes[count];
+ VK_CHECK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(r->dev->phy, r->surface, &count, presentModes));
+ r->presentMode = -1;
+ for (int i=0; i<count; i++){
+ if (presentModes[i] == presentMode) {
+ r->presentMode = presentModes[i];
+ break;
+ }
+ }
+ assert (r->presentMode >= 0);
+}
+
+void _swapchain_create (VkhPresenter r){
+ // Ensure all operations on the device have been finished before destroying resources
+ vkDeviceWaitIdle(r->dev->dev);
+
+ VkSurfaceCapabilitiesKHR surfCapabilities;
+ VK_CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(r->dev->phy, r->surface, &surfCapabilities));
+ assert (surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+
+ // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
+ if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
+ // If the surface size is undefined, the size is set to
+ // the size of the images requested
+ if (r->width < surfCapabilities.minImageExtent.width)
+ r->width = surfCapabilities.minImageExtent.width;
+ else if (r->width > surfCapabilities.maxImageExtent.width)
+ r->width = surfCapabilities.maxImageExtent.width;
+ if (r->height < surfCapabilities.minImageExtent.height)
+ r->height = surfCapabilities.minImageExtent.height;
+ else if (r->height > surfCapabilities.maxImageExtent.height)
+ r->height = surfCapabilities.maxImageExtent.height;
+ } else {
+ // If the surface size is defined, the swap chain size must match
+ r->width = surfCapabilities.currentExtent.width;
+ r->height= surfCapabilities.currentExtent.height;
+ }
+
+ VkSwapchainKHR newSwapchain;
+ VkSwapchainCreateInfoKHR createInfo = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ .surface = r->surface,
+ .minImageCount = surfCapabilities.minImageCount,
+ .imageFormat = r->format,
+ .imageColorSpace = r->colorSpace,
+ .imageExtent = {r->width,r->height},
+ .imageArrayLayers = 1,
+ .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .preTransform = surfCapabilities.currentTransform,
+ .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ .presentMode = r->presentMode,
+ .clipped = VK_TRUE,
+ .oldSwapchain = r->swapChain};
+
+ VK_CHECK_RESULT(vkCreateSwapchainKHR (r->dev->dev, &createInfo, NULL, &newSwapchain));
+ if (r->swapChain != VK_NULL_HANDLE)
+ _swapchain_destroy(r);
+ r->swapChain = newSwapchain;
+
+ VK_CHECK_RESULT(vkGetSwapchainImagesKHR(r->dev->dev, r->swapChain, &r->imgCount, NULL));
+ assert (r->imgCount>0);
+
+ VkImage images[r->imgCount];
+ VK_CHECK_RESULT(vkGetSwapchainImagesKHR(r->dev->dev, r->swapChain, &r->imgCount,images));
+
+ r->ScBuffers = (VkhImage*) malloc (r->imgCount * sizeof(VkhImage));
+ r->cmdBuffs = (VkCommandBuffer*)malloc (r->imgCount * sizeof(VkCommandBuffer));
+
+ for (int i=0; i<r->imgCount; i++) {
+
+ VkhImage sci = vkh_image_import(r->dev, images[i], r->format, r->width, r->height);
+ vkh_image_create_view(sci, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
+ r->ScBuffers [i] = sci;
+
+ r->cmdBuffs [i] = vkh_cmd_buff_create(r->dev, r->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ }
+ r->currentScBufferIndex = 0;
+}
+void _swapchain_destroy (VkhPresenter r){
+ for (uint32_t i = 0; i < r->imgCount; i++)
+ {
+ vkh_image_destroy (r->ScBuffers [i]);
+ vkFreeCommandBuffers (r->dev->dev, r->cmdPool, 1, &r->cmdBuffs[i]);
+ }
+ vkDestroySwapchainKHR (r->dev->dev, r->swapChain, NULL);
+ free(r->ScBuffers);
+ free(r->cmdBuffs);
+}
* THE SOFTWARE.
*/
#include "vkh_queue.h"
+#include "vkh_device.h"
#include "vkh.h"
-VkFence vkh_fence_create (VkDevice dev) {
+VkFence vkh_fence_create (VkhDevice dev) {
VkFence fence;
VkFenceCreateInfo fenceInfo = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = NULL,
.flags = 0 };
- VK_CHECK_RESULT(vkCreateFence(dev, &fenceInfo, NULL, &fence));
+ VK_CHECK_RESULT(vkCreateFence(dev->dev, &fenceInfo, NULL, &fence));
return fence;
}
-VkFence vkh_fence_create_signaled (VkDevice dev) {
+VkFence vkh_fence_create_signaled (VkhDevice dev) {
VkFence fence;
VkFenceCreateInfo fenceInfo = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = NULL,
.flags = VK_FENCE_CREATE_SIGNALED_BIT };
- VK_CHECK_RESULT(vkCreateFence(dev, &fenceInfo, NULL, &fence));
+ VK_CHECK_RESULT(vkCreateFence(dev->dev, &fenceInfo, NULL, &fence));
return fence;
}
-VkSemaphore vkh_semaphore_create (VkDevice dev) {
+VkSemaphore vkh_semaphore_create (VkhDevice dev) {
VkSemaphore semaphore;
VkSemaphoreCreateInfo info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = NULL,
.flags = 0};
- VK_CHECK_RESULT(vkCreateSemaphore(dev, &info, NULL, &semaphore));
+ VK_CHECK_RESULT(vkCreateSemaphore(dev->dev, &info, NULL, &semaphore));
return semaphore;
}
-VkCommandPool vkh_cmd_pool_create (VkDevice dev, uint32_t qFamIndex, VkCommandPoolCreateFlags flags){
+VkCommandPool vkh_cmd_pool_create (VkhDevice 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));
+ VK_CHECK_RESULT (vkCreateCommandPool(dev->dev, &cmd_pool_info, NULL, &cmdPool));
return cmdPool;
}
-VkCommandBuffer vkh_cmd_buff_create (VkDevice dev, VkCommandPool cmdPool, VkCommandBufferLevel level){
+VkCommandBuffer vkh_cmd_buff_create (VkhDevice 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));
+ VK_CHECK_RESULT (vkAllocateCommandBuffers (dev->dev, &cmd, &cmdBuff));
return cmdBuff;
}