quick backup
[demo] / src / vulkan / vkutil.cc
index 051ee4d..698e6f8 100644 (file)
 
 /* global variables */
 
+VkPipeline *vkgraphics_pipeline;
+VkFramebuffer *vkfbufs;
+VkRenderPass vkrpass;
 VkSwapchainKHR vkswapchain;
 VkImage *vkswapchain_images;
+VkImageView *vkswapchain_views;
+int vknum_swapchain_images;
 int vknext_swapchain_image;
 VkSurfaceKHR vksurface;
 VkInstance vkinst;
@@ -46,10 +51,7 @@ bool vku_have_extension(const char *name)
                vkext_count = 0;
                vkEnumerateInstanceExtensionProperties(0, &vkext_count, 0);
                if(vkext_count) {
-                       if(!(vkext = (VkExtensionProperties *)malloc(vkext_count * sizeof *vkext))) {
-                               perror("failed to allocate instance extension list");
-                               return false;
-                       }
+                       vkext = new VkExtensionProperties[vkext_count];
                        vkEnumerateInstanceExtensionProperties(0, &vkext_count, vkext);
 
                        printf("instance extensions:\n");
@@ -75,10 +77,7 @@ bool vku_have_device_extension(const char *name)
                vkdevext_count = 0;
                vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, 0);
                if(vkdevext_count) {
-                       if(!(vkdevext = (VkExtensionProperties *)malloc(vkdevext_count * sizeof *vkdevext))) {
-                               perror("failed to allocate device extension list");
-                               return false;
-                       }
+                       vkdevext = new VkExtensionProperties[vkdevext_count];
                        vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, vkdevext);
 
                        printf("selected device extensions:\n");
@@ -137,7 +136,7 @@ bool vku_create_device()
                fprintf(stderr, "failed to enumerate vulkan physical devices\n");
                return false;
        }
-       phys_devices = (VkPhysicalDevice *)malloc(num_devices * sizeof *phys_devices);
+       phys_devices = new VkPhysicalDevice[num_devices];
        if(vkEnumeratePhysicalDevices(vkinst, &num_devices, phys_devices) != 0) {
                fprintf(stderr, "failed to enumerate vulkan physical devices\n");
                return false;
@@ -179,7 +178,7 @@ bool vku_create_device()
                if(qprop_count <= 0) {
                        continue;
                }
-               qprop = (VkQueueFamilyProperties *)malloc(qprop_count * sizeof *qprop);
+               qprop = new VkQueueFamilyProperties[qprop_count];
                vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, qprop);
 
                for(unsigned int j=0; j<qprop_count; j++) {
@@ -192,7 +191,7 @@ bool vku_create_device()
                                sel_qfamily = j;
                        }
                }
-               free(qprop);
+               delete [] qprop;
        }
 
        if(sel_dev < 0 || sel_qfamily < 0) {
@@ -263,7 +262,7 @@ void vku_cleanup()
                vkinst = 0;
        }
 
-       free(phys_devices);
+       delete [] phys_devices;
        phys_devices = 0;
 }
 
@@ -359,15 +358,42 @@ VkImage *vku_get_swapchain_images(VkSwapchainKHR sc, int *count)
        if(vkGetSwapchainImagesKHR(vkdev, sc, &nimg, 0) != 0) {
                return 0;
        }
-       if(!(images = (VkImage *)malloc(nimg * sizeof *images))) {
-               return 0;
-       }
+       images = new VkImage[nimg];
        vkGetSwapchainImagesKHR(vkdev, sc, &nimg, images);
 
        if(count) *count = (int)nimg;
        return images;
 }
 
+VkImageView *vku_create_image_views(VkImage *images, int count)
+{
+       VkImageView *iviews;
+
+       iviews = new VkImageView[count];
+       for(int i=0; i<count; i++) {
+               VkImageViewCreateInfo inf;
+               memset(&inf, 0, sizeof inf);
+
+               inf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+               inf.image = images[i];
+               inf.viewType = VK_IMAGE_VIEW_TYPE_2D;
+               inf.format = VK_FORMAT_B8G8R8A8_UNORM; //TODO
+               inf.components.r = inf.components.g = inf.components.b =
+                       inf.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+               inf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+               inf.subresourceRange.levelCount = 1;
+               inf.subresourceRange.layerCount = 1;
+
+               if(vkCreateImageView(vkdev, &inf, 0, iviews) != 0) {
+                       fprintf(stderr, "Failed to create image views.\n");
+                       delete iviews;
+                       return 0;
+               }
+       }
+
+       return iviews;
+}
+
 int vku_get_next_image(VkSwapchainKHR sc)
 {
        uint32_t next;
@@ -394,15 +420,95 @@ void vku_present(VkSwapchainKHR sc, int img_idx)
        vkQueuePresentKHR(vkq, &inf);
 }
 
+bool vku_create_renderpass()
+{
+       VkAttachmentDescription attachments[2];
+       memset(&attachments, 0, 2 * sizeof *attachments);
+
+       /* color */
+       attachments[0].format = VK_FORMAT_B8G8R8A8_UNORM;
+       attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+       attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+       attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+       attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+       attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+       attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+       attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+       /* depth */
+       attachments[1].format = VK_FORMAT_D32_SFLOAT_S8_UINT; //TODO
+       attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
+       attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+       attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+       attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+       attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+       attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+       attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+       VkAttachmentReference color_ref;
+       color_ref.attachment = 0;
+       color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+       VkAttachmentReference depth_ref;
+       depth_ref.attachment = 1;
+       depth_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+       VkSubpassDescription subpass_desc;
+       memset(&subpass_desc, 0, sizeof subpass_desc);
+
+       subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+       subpass_desc.colorAttachmentCount = 1;
+       subpass_desc.pColorAttachments = &color_ref;
+       subpass_desc.pDepthStencilAttachment = &depth_ref;
+
+       VkRenderPassCreateInfo inf;
+       memset(&inf, 0, sizeof inf);
+
+       inf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+       inf.attachmentCount = 2;
+       inf.pAttachments = attachments;
+       inf.subpassCount = 1;
+       inf.pSubpasses = &subpass_desc;
+
+       if(vkCreateRenderPass(vkdev, &inf, 0, &vkrpass) != VK_SUCCESS) {
+               return false;
+       }
+
+       return true;
+}
+
+bool vku_create_framebuffers(VkImageView *image_views, int count, int w, int h)
+{
+       delete vkfbufs;
+       vkfbufs = new VkFramebuffer[count];
+
+       VkFramebufferCreateInfo inf;
+       memset(&inf, 0, sizeof inf);
+
+       inf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+       inf.renderPass = vkrpass;
+       inf.attachmentCount = count;
+       inf.pAttachments = image_views;
+       inf.width = w;
+       inf.height = h;
+       inf.layers = 1;
+
+       for(int i=0; i<count; i++) {
+               if(vkCreateFramebuffer(vkdev, &inf, 0, &vkfbufs[i]) != VK_SUCCESS) {
+                       fprintf(stderr, "Failed to create framebuffer for image view: %d\n", i);
+                       delete vkfbufs;
+                       return false;
+               }
+       }
+       return true;
+}
+
 struct vku_buffer *vku_create_buffer(int sz, unsigned int usage)
 {
        struct vku_buffer *buf;
        VkBufferCreateInfo binfo;
 
-       if(!(buf = (vku_buffer *)malloc(sizeof *buf))) {
-               perror("failed to allocate vk_buffer structure");
-               return 0;
-       }
+       buf = new vku_buffer;
 
        memset(&binfo, 0, sizeof binfo);
        binfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@@ -422,7 +528,7 @@ void vku_destroy_buffer(struct vku_buffer *buf)
 {
        if(buf) {
                vkDestroyBuffer(vkdev, buf->buf, 0);
-               free(buf);
+               delete buf;
        }
 }
 
@@ -754,6 +860,80 @@ const char *vku_get_vulkan_error_str(VkResult error)
        return errmsg.c_str();
 }
 
+bool vku_create_graphics_pipeline(VkPipelineLayout *layout)
+{
+       VkGraphicsPipelineCreateInfo inf;
+       memset(&inf, 0, sizeof inf);
+
+       inf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+       inf.layout = *layout;
+       inf.renderPass = vkrpass;
+
+       /* states */
+
+       /* how primitives are assembled */
+       VkPipelineInputAssemblyStateCreateInfo ias;
+       memset(&ias, 0, sizeof ias);
+       ias.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+       ias.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+
+       /* rasterisation */
+       VkPipelineRasterizationStateCreateInfo rsi;
+       memset(&rsi, 0, sizeof rsi);
+       rsi.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+       rsi.polygonMode = VK_POLYGON_MODE_FILL;
+       rsi.cullMode = VK_CULL_MODE_BACK_BIT;
+       rsi.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+       rsi.lineWidth = 1.0f;
+
+       /* blend factors */
+       VkPipelineColorBlendAttachmentState bas[1];
+       memset(&bas[0], 0, sizeof bas[0]);
+
+       VkPipelineColorBlendStateCreateInfo cbs;
+       memset(&cbs, 0, sizeof cbs);
+       cbs.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+       cbs.attachmentCount = 1;
+       cbs.pAttachments = bas;
+
+       /* number of viewport and scissors in this pipeline */
+       VkPipelineViewportStateCreateInfo vs;
+       memset(&vs, 0, sizeof vs);
+       vs.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+       vs.viewportCount = 1;
+       vs.scissorCount = 1;
+
+       /* dynamic states: that can be changed later */
+       std::vector<VkDynamicState> ds_enabled;
+       ds_enabled.push_back(VK_DYNAMIC_STATE_VIEWPORT);
+       //ds_enabled.push_back(VK_DYNAMIC_STATE_SCISSOR);
+       VkPipelineDynamicStateCreateInfo ds;
+       ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+       ds.pDynamicStates = ds_enabled.data();
+       ds.dynamicStateCount = static_cast<uint32_t>(ds_enabled.size());
+
+       /* depth tests */
+       VkPipelineDepthStencilStateCreateInfo dsi;
+       memset(&dsi, 0, sizeof dsi);
+       dsi.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+       dsi.depthTestEnable = VK_TRUE;
+       dsi.depthWriteEnable = VK_TRUE;
+       dsi.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+       dsi.back.failOp = VK_STENCIL_OP_KEEP;
+       dsi.back.passOp = VK_STENCIL_OP_KEEP;
+       dsi.back.compareOp = VK_COMPARE_OP_ALWAYS;
+       dsi.front = dsi.back;
+
+       /* multisampling - must be set even if not used */
+       VkPipelineMultisampleStateCreateInfo msi;
+       memset(&msi, 0, sizeof msi);
+       msi.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+       msi.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+
+       //TODO in progress
+       return true;
+}
+
 static const char *get_device_name_str(VkPhysicalDeviceType type)
 {
        switch(type) {