#include <string>
#include <vector>
+#include <gmath/gmath.h>
+
#include "gfxapi.h"
#include "vkutil.h"
extern int win_w;
extern int win_h;
+VkCommandBuffer *swapchain_cmd_bufs;
+
/* static functions */
static void error_callback(int error, const char *descr);
static void clear(float r, float g, float b);
static void zbuffer(bool enable);
static void cull_face(Gfx_cull_face cf);
static void reshape(int width, int height);
+static void swapbuffers();
+static void begin_drawing();
+static void end_drawing();
+
+static bool create_swapchain_cmd_bufs(VkCommandPool vkcmdpool);
+static bool record_cmd_clear(float r, float g, float b);
bool init_vulkan()
{
+ gfx_clear = clear;
+ gfx_viewport = viewport;
+ gfx_zbuffer = zbuffer;
+ gfx_cull_face = cull_face;
+ gfx_reshape = reshape;
+ gfx_swapbuffers = swapbuffers;
+ gfx_begin_drawing = begin_drawing;
+ gfx_end_drawing = end_drawing;
+
if(!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW.\n");
return false;
return false;
}
+ if(!vku_create_semaphores())
+ return false;
+
if(!(vkswapchain = vku_create_swapchain(vksurface, win_w, win_h, 2,
VK_PRESENT_MODE_FIFO_KHR, 0))) {
fprintf(stderr, "Failed to create swapchain.\n");
return false;
}
- vkswapchain_views = vku_create_image_views(vkswapchain_images, vknum_swapchain_images);
- if(!vkswapchain_views) {
- fprintf(stderr, "Failed to create swapchain image views.\n");
- delete [] vkswapchain_images;
- return false;
- }
-
- if(!vku_create_renderpass()) {
- fprintf(stderr, "Failed to create renderpass'\n");
+ /* vkswapchain_views = vku_create_image_views(vkswapchain_images, vknum_swapchain_images);
+ if(!vkswapchain_views) {
+ fprintf(stderr, "Failed to create swapchain image views.\n");
+ delete [] vkswapchain_images;
+ return false;
+ }
+ */
+ if(!create_swapchain_cmd_bufs(vkcmdpool)) {
return false;
}
- if(!vku_create_framebuffers(vkswapchain_views, vknum_swapchain_images, win_w, win_h)) {
- fprintf(stderr, "Failed to create framebuffers.\n");
+ if(!record_cmd_clear(1.0, 0.1, 0.1))
return false;
- }
-
- gfx_clear = clear;
- gfx_viewport = viewport;
- gfx_zbuffer = zbuffer;
- gfx_cull_face = cull_face;
- gfx_reshape = reshape;
return true;
}
void cleanup_vulkan()
{
+ vkFreeCommandBuffers(vkdev, vkcmdpool, vknum_swapchain_images, swapchain_cmd_bufs);
if(win) {
glfwDestroyWindow(win);
}
//TODOs according to the book:
// 1- make sure all threads have been terminated (when I add threads)
-
- // 2- destroy objects in *reverse* order
- vkDestroyRenderPass(vkdev, vkrpass, 0);
- vkDestroySurfaceKHR(vkinst, vksurface, 0);
-
vku_cleanup();
}
delete [] vkswapchain_images;
vkswapchain_images = vku_get_swapchain_images(sc, 0);
- vknext_swapchain_image = vku_get_next_image(vkswapchain);
+ vk_curr_swapchain_image = vku_get_next_image(vkswapchain);
}
static void clear(float r, float g, float b)
static void cull_face(Gfx_cull_face cf)
{
}
+
+static void swapbuffers()
+{
+}
+
+static void begin_drawing()
+{
+ if((vk_curr_swapchain_image = vku_get_next_image(vkswapchain)) == -1) {
+ fprintf(stderr, "Failed to get swapchain image. Exiting.\n");
+ exit(1);
+ }
+}
+
+static void end_drawing()
+{
+ /* submit queue */
+
+ VkSubmitInfo sinf;
+ memset(&sinf, 0, sizeof sinf);
+ sinf.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ sinf.waitSemaphoreCount = 1;
+ sinf.pWaitSemaphores = &vk_img_avail_sema;
+ sinf.signalSemaphoreCount = 1;
+ sinf.pSignalSemaphores = &vk_rend_done_sema;
+
+ // the queue should wait on the semaphore
+
+ VkPipelineStageFlags wait_flags = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ sinf.pWaitDstStageMask = &wait_flags;
+ sinf.commandBufferCount = 1;
+ sinf.pCommandBuffers = &swapchain_cmd_bufs[vk_curr_swapchain_image];
+
+ if(vkQueueSubmit(vkq, 1, &sinf, VK_NULL_HANDLE) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to submit drawing command buffer\n");
+ exit(1);
+ }
+
+ /* present drawn image */
+ VkPresentInfoKHR pinf;
+ memset(&pinf, 0, sizeof pinf);
+ pinf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ pinf.waitSemaphoreCount = 1;
+ pinf.pWaitSemaphores = &vk_rend_done_sema;
+ pinf.swapchainCount = 1;
+ pinf.pSwapchains = &vkswapchain;
+ pinf.pImageIndices = (uint32_t *)&vk_curr_swapchain_image;
+
+ if(vkQueuePresentKHR(vkq, &pinf) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to submit presentation command buffer.\n");
+ exit(1);
+ }
+}
+
+static bool record_cmd_clear(float r, float g, float b)
+{
+ VkCommandBufferBeginInfo binf;
+ binf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ binf.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
+
+ /* this function must be called outside a renderpass instance */
+ const VkClearColorValue pcolor[4] = {r, g, b, 1.0};
+
+ VkImageSubresourceRange range;
+ memset(&range, 0, sizeof range);
+ range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ range.baseMipLevel = 0;
+ range.baseArrayLayer = 0;
+ range.layerCount = 1;
+
+ for(int i=0; i<vknum_swapchain_images; i++) {
+ /* layout for clearing */
+ VkImageMemoryBarrier cb;
+ memset(&cb, 0, sizeof cb);
+ cb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ cb.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ cb.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ cb.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ cb.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ cb.srcQueueFamilyIndex = vkqfamily;
+ cb.dstQueueFamilyIndex = vkqfamily;
+ cb.image = vkswapchain_images[i];
+ cb.subresourceRange = range;
+
+ /* layout for presenting */
+ VkImageMemoryBarrier pb;
+ memset(&pb, 0, sizeof pb);
+ pb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ pb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ pb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ pb.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ pb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ pb.srcQueueFamilyIndex = vkqfamily;
+ pb.dstQueueFamilyIndex = vkqfamily;
+ pb.image = vkswapchain_images[i];
+ pb.subresourceRange = range;
+
+ vkBeginCommandBuffer(swapchain_cmd_bufs[i], &binf);
+ vkCmdPipelineBarrier(swapchain_cmd_bufs[i], VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, 0, 0, 1, &pb);
+
+ vkCmdClearColorImage(swapchain_cmd_bufs[i], vkswapchain_images[vk_curr_swapchain_image], VK_IMAGE_LAYOUT_GENERAL,
+ pcolor, 1, &range);
+
+ vkCmdPipelineBarrier(swapchain_cmd_bufs[i], VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &cb);
+
+ if(vkEndCommandBuffer(swapchain_cmd_bufs[i]) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to record command buffer.\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool create_swapchain_cmd_bufs(VkCommandPool cpool)
+{
+ swapchain_cmd_bufs = new VkCommandBuffer[vknum_swapchain_images];
+
+ VkCommandBufferAllocateInfo ainf;
+ memset(&ainf, 0, sizeof ainf);
+
+ ainf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ ainf.commandPool = cpool;
+ ainf.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ ainf.commandBufferCount = (uint32_t)vknum_swapchain_images;
+
+ if(vkAllocateCommandBuffers(vkdev, &ainf, swapchain_cmd_bufs) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to allocate the swapchain command buffers.\n");
+ return false;
+ }
+
+ return true;
+}