diff options
| -rw-r--r-- | src/graphics.c | 247 | ||||
| -rw-r--r-- | src/graphics.h | 9 | ||||
| -rw-r--r-- | src/main.c | 13 | 
3 files changed, 181 insertions, 88 deletions
| diff --git a/src/graphics.c b/src/graphics.c index 0e77c3a..95f6630 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -6,15 +6,14 @@  #include "graphics.h"  #include "common.h" -// TODO: finish buffer_copy - -// TODO: explicitly make a transfer queue for -//       the buffer staging/copying -// TODO: vkAllocateMemory shouldn't be called for every buffer, -//       a memory allocator should be used (the offset parameter) +// TODO: the amount of vertices is currently +//       hardcoded in command_buffer_record +//       thats bad  // TODO: add more error checking  // TODO: add log output  // TODO: check for memory leaks +// TODO: vkAllocateMemory shouldn't be called for every buffer, +//       a memory allocator should be used (the offset parameter)  #define SWAP_CHAIN_IMAGES 3 @@ -47,6 +46,9 @@ struct queue_family_idx {      u32 present_family;      bool has_present_family; + +    u32 transfer_family; +    bool has_transfer_family;  };  struct swap_chain_support_details { @@ -78,8 +80,13 @@ static void destroy_swap_chain(graphics_t graphics);  // static void destroy_command_pool(graphics_t graphics);  static void destroy_sync_objects(graphics_t graphics); +static int buffer_create(graphics_t graphics, size_t size, VkBufferUsageFlags usageflg, +                         VkMemoryPropertyFlags propflg, buffer_t *buffer); +static int buffer_copy(graphics_t graphics, buffer_t dest, buffer_t src, size_t size); +static void buffer_destroy(graphics_t graphics, buffer_t buffer); +  // --- Helper Functions --- -static char *str_VkResult(VkResult result); +static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx);  static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface);  static bool device_has_extension_support(VkPhysicalDevice phy_device); @@ -95,21 +102,18 @@ static int swap_chain_choose_format(VkSurfaceFormatKHR* formats, u32 nformats, V  static int swap_chain_choose_present_mode(VkPresentModeKHR *modes, u32 nmodes, VkPresentModeKHR *mode);  static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent2D *extent); -#define CMND graphics->command +#define CMND graphics->command_graphics +#define CMND_TRNS graphics->command_transfer  static int command_buffer_record(graphics_t graphics, u32 image_index);  #define SYNC graphics->sync  #define VBFF graphics->vertex_buffer +#define IBFF graphics->index_buffer +static int graphics_buffer_create(graphics_t graphics, VkBufferUsageFlags flags, void *data, size_t size, buffer_t *buffer);  static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc); -static int buffer_create(VkDevice device, VkPhysicalDevice physical_device, -                         VkDeviceSize size, VkBufferUsageFlags usageflg, -                         VkMemoryPropertyFlags propflg, buffer_t *buffer); -static void buffer_destroy(VkDevice device, buffer_t buffer); -static int buffer_copy(VkBuffer dest, VkBuffer, VkBuffer src, VkDeviceSize size, VkDevice devie, VkCommandPool pool, u32 queue_idx); -static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx); - +static char *str_VkResult(VkResult result);  F_LOAD_FILE_ALIGNED(u32) // from config.h  // --- Debug Functions --- @@ -170,8 +174,8 @@ graphics_t graphics_create(struct graphics_info *info)      CCHECK(create_logical_device);      CCHECK(create_pipeline);      CCHECK(create_swap_chain); -    CCHECK(create_vertex_buffer);      CCHECK(create_command_pool); +    CCHECK(create_vertex_buffer);      CCHECK(create_sync_objects);      return graphics;     @@ -189,8 +193,10 @@ void graphics_destroy(graphics_t graphics)      destroy_sync_objects(graphics);      vkDestroyCommandPool(graphics->logical_device, CMND.pool, NULL); +    vkDestroyCommandPool(graphics->logical_device, CMND_TRNS.pool, NULL); -    buffer_destroy(graphics->logical_device, VBFF); +    buffer_destroy(graphics, VBFF); +    buffer_destroy(graphics, IBFF);      destroy_swap_chain(graphics);      destroy_pipeline(graphics); @@ -397,7 +403,7 @@ static int create_logical_device(graphics_t graphics, struct graphics_info *info      // queue infos          u32 unique_queue_family_count = 0;      u32 queue_indices[] = { -        indices.graphics_family, indices.present_family, +        indices.graphics_family, indices.present_family, indices.transfer_family      };      VkDeviceQueueCreateInfo queue_infos[ARR_SIZE(queue_indices)] = {0}; @@ -448,6 +454,7 @@ static int create_logical_device(graphics_t graphics, struct graphics_info *info      vkGetDeviceQueue(graphics->logical_device, indices.graphics_family, 0, &graphics->graphics_queue);      vkGetDeviceQueue(graphics->logical_device, indices.present_family, 0, &graphics->present_queue); +    vkGetDeviceQueue(graphics->logical_device, indices.transfer_family, 0, &graphics->transfer_queue);      ret = 0;  exit: @@ -791,22 +798,40 @@ static int create_command_pool(graphics_t graphics, struct graphics_info *info)      struct queue_family_idx indices;      device_queue_families(graphics->physical_device, graphics->surface, &indices); -     -    VkCommandPoolCreateInfo pool_info = {0}; -    pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; -    pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; -    pool_info.queueFamilyIndex = indices.graphics_family; -    VCHECK(vkCreateCommandPool, graphics->logical_device, &pool_info, NULL, &CMND.pool); +    // graphics pool +    VkCommandPoolCreateInfo graphics_pool_info = {0}; +    graphics_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; +    graphics_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; +    graphics_pool_info.queueFamilyIndex = indices.graphics_family; + +    VCHECK(vkCreateCommandPool, graphics->logical_device, &graphics_pool_info, NULL, &CMND.pool); + +    // graphics buffer +    VkCommandBufferAllocateInfo graphics_allocate_info = {0}; +    graphics_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; +    graphics_allocate_info.commandPool = CMND.pool; +    graphics_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; +    graphics_allocate_info.commandBufferCount = 1; + +    VCHECK(vkAllocateCommandBuffers, graphics->logical_device, &graphics_allocate_info, &CMND.buffer); + +    // transfer pool +    VkCommandPoolCreateInfo transfer_pool_info = {0}; +    transfer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; +    transfer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; +    transfer_pool_info.queueFamilyIndex = indices.transfer_family; -    // allocate the command buffer(s) -    VkCommandBufferAllocateInfo allocate_info = {0}; -    allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; -    allocate_info.commandPool = CMND.pool; -    allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; -    allocate_info.commandBufferCount = 1; +    VCHECK(vkCreateCommandPool, graphics->logical_device, &transfer_pool_info, NULL, &CMND_TRNS.pool); -    VCHECK(vkAllocateCommandBuffers, graphics->logical_device, &allocate_info, &CMND.buffer); +    // graphics buffer +    VkCommandBufferAllocateInfo transfer_allocate_info = {0}; +    transfer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; +    transfer_allocate_info.commandPool = CMND_TRNS.pool; +    transfer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; +    transfer_allocate_info.commandBufferCount = 1; + +    VCHECK(vkAllocateCommandBuffers, graphics->logical_device, &transfer_allocate_info, &CMND_TRNS.buffer);      ret = 0;  exit: @@ -843,26 +868,94 @@ static void destroy_sync_objects(graphics_t graphics)  static int create_vertex_buffer(graphics_t graphics, struct graphics_info *info)  { -    (void)info; +    graphics_buffer_create(graphics, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, info->vertices, +                           sizeof(*info->vertices) *info->nvertices, &VBFF); +    graphics_buffer_create(graphics, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, info->indices, +                           sizeof(*info->indices) * info->nindices, &IBFF); +    return 0; +} + +static int buffer_create(graphics_t graphics, size_t size, VkBufferUsageFlags usageflg, VkMemoryPropertyFlags propflg, buffer_t *buffer) +{      int ret = 1; -    size_t size = sizeof(*info->vertices) * info->nvertices; +    VkBufferCreateInfo buffer_info = {0}; +    buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; +    buffer_info.size = size; +    buffer_info.usage = usageflg; -    buffer_create(graphics->logical_device, graphics->physical_device, -                  size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, -                  (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | -                   VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), &VBFF); +    // share between the graphics nad transfer queue families +    struct queue_family_idx indices; +    device_queue_families(graphics->physical_device, graphics->surface, &indices); +    u32 queue_family_indices[] = { indices.graphics_family, indices.transfer_family }; +     +    // buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; +    buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT; +    buffer_info.pQueueFamilyIndices =  queue_family_indices; +    buffer_info.queueFamilyIndexCount = ARR_SIZE(queue_family_indices); + +    VCHECK(vkCreateBuffer, graphics->logical_device, &buffer_info, NULL, &buffer->buffer); -    void *data; -    vkMapMemory(graphics->logical_device, VBFF.memory, 0, size, 0, &data); -        memcpy(data, info->vertices, size); -    vkUnmapMemory(graphics->logical_device, VBFF.memory); +    VkMemoryRequirements memory_requirements; +    vkGetBufferMemoryRequirements(graphics->logical_device, buffer->buffer, &memory_requirements); +    VkMemoryAllocateInfo allocate_info = {0}; +    allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; +    allocate_info.allocationSize = memory_requirements.size; +     +    u32 memory_type_idx; +    buffer_find_memory_type(graphics->physical_device, memory_requirements.memoryTypeBits, propflg, &memory_type_idx); +    allocate_info.memoryTypeIndex = memory_type_idx; + +    VCHECK(vkAllocateMemory, graphics->logical_device, &allocate_info, NULL, &buffer->memory); +    VCHECK(vkBindBufferMemory, graphics->logical_device, buffer->buffer, buffer->memory, 0); +          ret = 0;  exit:      return ret;  } +static int buffer_copy(graphics_t graphics, buffer_t dest, buffer_t src, size_t size) +{ +    // TODO: add error checking +    int ret = 1; +     +    vkResetCommandBuffer(CMND_TRNS.buffer, 0); +     +    VkCommandBufferBeginInfo begin_info = {0}; +    begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; +    begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + +    vkBeginCommandBuffer(CMND_TRNS.buffer, &begin_info); + +    VkBufferCopy copy_region = {0}; +    copy_region.srcOffset = 0; // Optional +    copy_region.dstOffset = 0; // Optional +    copy_region.size = size; +     +    vkCmdCopyBuffer(CMND_TRNS.buffer, src.buffer, dest.buffer, 1, ©_region); +     +    vkEndCommandBuffer(CMND_TRNS.buffer); + +    VkSubmitInfo submit_info = {0}; +    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; +    submit_info.commandBufferCount = 1; +    submit_info.pCommandBuffers = &CMND_TRNS.buffer; + +    vkQueueSubmit(graphics->transfer_queue, 1, &submit_info, VK_NULL_HANDLE); +    vkQueueWaitIdle(graphics->transfer_queue); + +    ret = 0; +exit: +    return ret; +} + +static void buffer_destroy(graphics_t graphics, buffer_t buffer) +{ +    vkDestroyBuffer(graphics->logical_device, buffer.buffer, NULL); +    vkFreeMemory(graphics->logical_device, buffer.memory, NULL); +} +  static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family)  {         u32 count = 0; @@ -877,6 +970,11 @@ static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surfa              queue_family->has_graphics_family = true;          } +        if(properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) { +            queue_family->transfer_family = i; +            queue_family->has_transfer_family = true; +        } +          VkBool32 present_support = false;          vkGetPhysicalDeviceSurfaceSupportKHR(phy_device, i, surface, &present_support); @@ -897,7 +995,9 @@ static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface      return          (device_queue_families(phy_device, surface, &indices), -         indices.has_graphics_family && indices.has_present_family) +         indices.has_graphics_family && +         indices.has_present_family && +         indices.has_transfer_family)          &&          (device_has_extension_support(phy_device))          && @@ -1056,6 +1156,8 @@ static int command_buffer_record(graphics_t graphics, u32 image_index)      VkDeviceSize offsets[] = {0};      vkCmdBindVertexBuffers(CMND.buffer, 0, 1, vertex_buffers, offsets); +    vkCmdBindIndexBuffer(CMND.buffer, IBFF.buffer, 0, VK_INDEX_TYPE_UINT32); +      VkViewport viewport = {0};      viewport.x = 0.0f;      viewport.y = 0.0f; @@ -1073,7 +1175,7 @@ static int command_buffer_record(graphics_t graphics, u32 image_index)      // 3 is the number of vertices      // TODO: fix this -    vkCmdDraw(CMND.buffer, 3, 1, 0, 0); +    vkCmdDrawIndexed(CMND.buffer, 6, 1, 0, 0, 0);      // Cleaning up      vkCmdEndRenderPass(CMND.buffer); @@ -1085,6 +1187,26 @@ exit:      return ret;  } +static int graphics_buffer_create(graphics_t graphics, VkBufferUsageFlags flags, void *data, size_t size, buffer_t *buffer) +{ +    buffer_t staging; +    buffer_create(graphics, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, +                  (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | +                   VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), &staging); + +    void *dest_data; +    vkMapMemory(graphics->logical_device, staging.memory, 0, size, 0, &dest_data); +        memcpy(dest_data, data, size); +    vkUnmapMemory(graphics->logical_device, staging.memory); + +    buffer_create(graphics, size, (flags | VK_BUFFER_USAGE_TRANSFER_DST_BIT), +                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffer); +     +    buffer_copy(graphics, *buffer, staging, size); +    buffer_destroy(graphics, staging); +    return 0; +} +  static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc)  {      binding_desc->binding = 0; @@ -1104,45 +1226,6 @@ static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding      return 0;  } -static int buffer_create(VkDevice device, VkPhysicalDevice physical_device, -                         VkDeviceSize size, VkBufferUsageFlags usageflg, -                         VkMemoryPropertyFlags propflg, buffer_t *buffer) -{ -    int ret = 1; -     -    VkBufferCreateInfo buffer_info = {0}; -    buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; -    buffer_info.size = size; -    buffer_info.usage = usageflg; -    buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - -    VCHECK(vkCreateBuffer, device, &buffer_info, NULL, &buffer->buffer); - -    VkMemoryRequirements memory_requirements; -    vkGetBufferMemoryRequirements(device, buffer->buffer, &memory_requirements); - -    VkMemoryAllocateInfo allocate_info = {0}; -    allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; -    allocate_info.allocationSize = memory_requirements.size; -     -    u32 memory_type_idx; -    buffer_find_memory_type(physical_device, memory_requirements.memoryTypeBits, propflg, &memory_type_idx); -    allocate_info.memoryTypeIndex = memory_type_idx; - -    VCHECK(vkAllocateMemory, device, &allocate_info, NULL, &buffer->memory); -    VCHECK(vkBindBufferMemory, device, buffer->buffer, buffer->memory, 0); - -    ret = 0; -exit: -    return ret; -} - -static void buffer_destroy(VkDevice device, buffer_t buffer) -{ -    vkDestroyBuffer(device, buffer.buffer, NULL); -    vkFreeMemory(device, buffer.memory, NULL); -} -  static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx)  {      VkPhysicalDeviceMemoryProperties properties; diff --git a/src/graphics.h b/src/graphics.h index 470ea9b..71a8889 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -33,6 +33,7 @@ typedef struct graphics {      VkQueue graphics_queue;      VkQueue present_queue; +    VkQueue transfer_queue;      VkSurfaceKHR surface; @@ -57,16 +58,16 @@ typedef struct graphics {      struct command {          VkCommandPool pool;          VkCommandBuffer buffer; -    } command; +    } command_graphics, command_transfer;      struct sync {          VkSemaphore semph_image_available;          VkSemaphore semph_render_finished;          VkFence     fence_inflight;      } sync; - +          buffer_t vertex_buffer; -    buffer_t staging_buffer; +    buffer_t index_buffer;  } * graphics_t; @@ -79,6 +80,8 @@ struct graphics_info {      vertex_t *vertices;      size_t nvertices; +    u32 *indices; +    size_t nindices;      int (*surface_func)(VkInstance instance, VkSurfaceKHR *surface);  }; @@ -11,9 +11,14 @@ graphics_t graphics;  int _create_surface(VkInstance instance, VkSurfaceKHR *surface);  vertex_t vertices[] = { -    {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, -    {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, -    {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} +    {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, +    {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}}, +    {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}, +    {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}} +}; + +u32 indices[] = { +    0, 1, 2, 2, 3, 0  };  int main(void) @@ -56,6 +61,8 @@ int main(void)      grph_info.vertices = vertices;      grph_info.nvertices = ARR_SIZE(vertices); +    grph_info.indices = indices; +    grph_info.nindices = ARR_SIZE(indices);      grph_info.surface_func = _create_surface; | 
