diff options
Diffstat (limited to 'src/graphics.c')
-rw-r--r-- | src/graphics.c | 276 |
1 files changed, 211 insertions, 65 deletions
diff --git a/src/graphics.c b/src/graphics.c index d603f68..e26d496 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -5,9 +5,6 @@ #include "graphics.h" #include "common.h" -// 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 @@ -87,8 +84,19 @@ static int buffer_create(graphics_t graphics, size_t size, VkBufferUsageFlags us 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); +static int image_create(graphics_t graphics, u32 width, u32 height, + VkFormat format, VkImageTiling tiling, + VkImageUsageFlags usage, VkMemoryPropertyFlags properties, + VkImageAspectFlags aspect_flags, image_t *image); +static void image_destroy(graphics_t graphics, image_t image); + // --- Helper Functions --- -static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx); +static int memory_find_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx); + +static int image_view_create(graphics_t graphics, VkFormat format, VkImageAspectFlags aspect_flags, + VkImage image, VkImageView *image_view); +static int image_format_filter(VkPhysicalDevice device, VkFormat *candidates, size_t ncandidates, + VkImageTiling tiling, VkFormatFeatureFlags features, VkFormat *format); static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface); static bool device_has_extension_support(VkPhysicalDevice phy_device); @@ -103,10 +111,11 @@ static void swap_chain_free_support_details(struct swap_chain_support_details *d static int swap_chain_choose_format(VkSurfaceFormatKHR* formats, u32 nformats, VkSurfaceFormatKHR *format); static int swap_chain_choose_present_mode(VkPresentModeKHR *modes, u32 nmodes, VkPresentModeKHR *mode); static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent2D *extent); +static int swap_chain_choose_depth_image_format(VkPhysicalDevice device, VkFormat *format); #define CMND graphics->command_graphics #define CMND_TRNS graphics->command_transfer -static int command_buffer_record(graphics_t graphics, u32 image_index); +static int command_buffer_record(graphics_t graphics, u32 image_index, u32 nvertices); #define UBOD graphics->ubo_descriptor @@ -184,7 +193,6 @@ graphics_t graphics_create(struct graphics_info *info) CCHECK(create_buffers); CCHECK(create_descriptors); CCHECK(create_sync_objects); - return graphics; fail: @@ -224,7 +232,7 @@ void graphics_destroy(graphics_t graphics) free(graphics); } -int graphics_draw_frame(graphics_t graphics) +int graphics_draw_frame(graphics_t graphics, u32 nvertices) { int ret = 1; @@ -247,7 +255,7 @@ int graphics_draw_frame(graphics_t graphics) // reset the command buffer vkResetCommandBuffer(CMND.buffer, 0); - command_buffer_record(graphics, image_index); + command_buffer_record(graphics, image_index, nvertices); UBO.update_ubo(UBO.mapped_data); @@ -284,10 +292,8 @@ int graphics_draw_frame(graphics_t graphics) present_info.pImageIndices = &image_index; present_info.pResults = NULL; // Optional - vkQueuePresentKHR(graphics->present_queue, &present_info); - ret = 0; exit: return ret; @@ -546,38 +552,29 @@ static int create_swap_chain(graphics_t graphics, struct graphics_info *info) vkGetSwapchainImagesKHR(graphics->logical_device, SWCH.swap_chain, &SWCH.nimages, SWCH.images); for(u32 i = 0; i < SWCH.nimages; i++) - { - VkImageViewCreateInfo create_info = {0}; - create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - create_info.image = SWCH.images[i]; - - create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - create_info.format = surface_format.format; - - create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - - create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - create_info.subresourceRange.baseMipLevel = 0; - create_info.subresourceRange.levelCount = 1; - create_info.subresourceRange.baseArrayLayer = 0; - create_info.subresourceRange.layerCount = 1; - - VCHECK(vkCreateImageView, graphics->logical_device, &create_info, NULL, &SWCH.image_views[i]); - } + image_view_create(graphics, surface_format.format, + VK_IMAGE_ASPECT_COLOR_BIT, + SWCH.images[i], &SWCH.image_views[i]); + + VkFormat depth_format; + swap_chain_choose_depth_image_format(graphics->physical_device, &depth_format); + + // creating the depth image + ECHECK(image_create, graphics, extent.width, extent.height, depth_format, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT, &SWCH.depth_image); for(u32 i = 0; i < SWCH.nimages; i++) { VkImageView attachments[] = { - SWCH.image_views[i] + SWCH.image_views[i], + SWCH.depth_image.image_view }; VkFramebufferCreateInfo framebuffer_info = {0}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = PPLN.render_pass; - framebuffer_info.attachmentCount = 1; + framebuffer_info.attachmentCount = ARR_SIZE(attachments); framebuffer_info.pAttachments = attachments; framebuffer_info.width = SWCH.extent.width; framebuffer_info.height = SWCH.extent.height; @@ -604,6 +601,8 @@ static void destroy_swap_chain(graphics_t graphics) free(SWCH.image_views); free(SWCH.framebuffers); } + + image_destroy(graphics, SWCH.depth_image); vkDestroySwapchainKHR(graphics->logical_device, SWCH.swap_chain, NULL); } @@ -672,10 +671,8 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) // it is actually counter clocwise because // the y axis was reversed - // but cull mode is NONE so both sides are shown - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.cullMode = VK_CULL_MODE_NONE; - + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; rasterizer.depthBiasEnable = VK_FALSE; rasterizer.depthBiasConstantFactor = 0.0f; // Optional @@ -691,6 +688,7 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) multisampling.alphaToCoverageEnable = VK_FALSE; // Optional multisampling.alphaToOneEnable = VK_FALSE; // Optional + // Color Blend VkPipelineColorBlendAttachmentState color_blend_attachment = {0}; color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; color_blend_attachment.blendEnable = VK_FALSE; @@ -711,8 +709,20 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) color_blend.blendConstants[1] = 0.0f; // Optional color_blend.blendConstants[2] = 0.0f; // Optional color_blend.blendConstants[3] = 0.0f; // Optional + + // Depth Stencil State + VkPipelineDepthStencilStateCreateInfo depth_info = {0}; + depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_info.depthTestEnable = VK_TRUE; + depth_info.depthWriteEnable = VK_TRUE; + depth_info.depthCompareOp = VK_COMPARE_OP_LESS; + depth_info.depthBoundsTestEnable = VK_FALSE; + depth_info.minDepthBounds = 0.0f; // Optional + depth_info.maxDepthBounds = 1.0f; // Optional + depth_info.stencilTestEnable = VK_FALSE; - // Create UBO Descriptor + // Create Pipeline Layout + // ubo descriptor VkDescriptorSetLayoutBinding ubo_layout_binding = {0}; ubo_layout_binding.binding = 0; ubo_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -727,7 +737,7 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) VCHECK(vkCreateDescriptorSetLayout, graphics->logical_device, &descriptor_set_layout_info, NULL, &PPLN.descriptor_layout); - // Create Pipeline Layout + // pipeline layout VkPipelineLayoutCreateInfo pipeline_layout_info = {0}; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeline_layout_info.setLayoutCount = 1; @@ -745,8 +755,9 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) swap_chain_support(graphics->physical_device, graphics->surface, &details); swap_chain_choose_format(details.formats, details.nformats, &surface_format); swap_chain_free_support_details(&details); - + // Create Render Pass + // color attachment VkAttachmentDescription color_attachment = {0}; color_attachment.format = surface_format.format; color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; @@ -760,28 +771,57 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) VkAttachmentReference color_attachment_ref = {0}; color_attachment_ref.attachment = 0; color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDependency dependency = {0}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + // depth attachemnt + VkAttachmentDescription depth_attachment = {0}; + swap_chain_choose_depth_image_format(graphics->physical_device, &depth_attachment.format); + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depth_attachment_ref = {0}; + depth_attachment_ref.attachment = 1; + depth_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + VkSubpassDependency depth_dependency = {0}; + depth_dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + depth_dependency.dstSubpass = 0; + depth_dependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + depth_dependency.srcAccessMask = 0; + depth_dependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + depth_dependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + // subpass VkSubpassDescription subpass = {0}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &color_attachment_ref; + subpass.pDepthStencilAttachment = &depth_attachment_ref; - VkSubpassDependency dependency = {0}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkAttachmentDescription attachments[] = { color_attachment, depth_attachment }; + VkSubpassDependency dependencies[] = { dependency, depth_dependency }; + // render pass VkRenderPassCreateInfo render_pass_info = {0}; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; + render_pass_info.attachmentCount = ARR_SIZE(attachments); + render_pass_info.pAttachments = attachments; render_pass_info.subpassCount = 1; render_pass_info.pSubpasses = &subpass; - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = &dependency; + render_pass_info.dependencyCount = ARR_SIZE(dependencies); + render_pass_info.pDependencies = dependencies; VCHECK(vkCreateRenderPass, graphics->logical_device, &render_pass_info, NULL, &PPLN.render_pass); @@ -796,7 +836,7 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) pipeline_info.pViewportState = &viewport_state; pipeline_info.pRasterizationState = &rasterizer; pipeline_info.pMultisampleState = &multisampling; - pipeline_info.pDepthStencilState = NULL; + pipeline_info.pDepthStencilState = &depth_info; pipeline_info.pColorBlendState = &color_blend; pipeline_info.pDynamicState = &dynamic_state; @@ -1008,7 +1048,7 @@ static int buffer_create(graphics_t graphics, size_t size, VkBufferUsageFlags us allocate_info.allocationSize = memory_requirements.size; u32 memory_type_idx; - buffer_find_memory_type(graphics->physical_device, memory_requirements.memoryTypeBits, propflg, &memory_type_idx); + memory_find_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); @@ -1060,6 +1100,57 @@ static void buffer_destroy(graphics_t graphics, buffer_t buffer) vkFreeMemory(graphics->logical_device, buffer.memory, NULL); } +static int image_create(graphics_t graphics, u32 width, u32 height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usageflg, VkMemoryPropertyFlags propflg, VkImageAspectFlags aspect_flags, image_t *image) +{ + int ret = 0; + + VkImageCreateInfo image_info = {0}; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.extent.width = width; + image_info.extent.height = height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.format = format; + image_info.tiling = tiling; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_info.usage = usageflg; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VCHECK(vkCreateImage, graphics->logical_device, &image_info, NULL, &image->image); + + VkMemoryRequirements memory_requirements; + vkGetImageMemoryRequirements(graphics->logical_device, image->image, &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; + memory_find_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, &image->memory); + VCHECK(vkBindImageMemory, graphics->logical_device, image->image, image->memory, 0); + + ECHECK(image_view_create, graphics, format, aspect_flags, image->image, &image->image_view); + + ret = 0; +exit: + return ret; +} + +static void image_destroy(graphics_t graphics, image_t image) +{ + vkDestroyImageView(graphics->logical_device, image.image_view, NULL); + vkDestroyImage(graphics->logical_device, image.image, NULL); + vkFreeMemory(graphics->logical_device, image.memory, NULL); +} + +// Helper Functions + static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family) { u32 count = 0; @@ -1202,6 +1293,14 @@ static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent return 1; } +static int swap_chain_choose_depth_image_format(VkPhysicalDevice device, VkFormat *format) +{ + VkFormat candidates[] = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT }; + + return image_format_filter(device, candidates, ARR_SIZE(candidates), VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, format); +} + static int pipeline_load_shader_module(VkDevice device, char *path, VkShaderModule *module) { int ret = 1; @@ -1226,7 +1325,7 @@ exit: return ret; } -static int command_buffer_record(graphics_t graphics, u32 image_index) +static int command_buffer_record(graphics_t graphics, u32 image_index, u32 nvertices) { int ret = 1; @@ -1247,9 +1346,12 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) render_pass_info.renderArea.offset = (VkOffset2D){0, 0}; render_pass_info.renderArea.extent = SWCH.extent; - VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - render_pass_info.clearValueCount = 1; - render_pass_info.pClearValues = &clear_color; + VkClearValue clear_values[2] = {0}; + clear_values[0].color = (VkClearColorValue){{0.0f, 0.0f, 0.0f, 1.0f}}; + clear_values[1].depthStencil = (VkClearDepthStencilValue){1.0f, 0}; + + render_pass_info.clearValueCount = ARR_SIZE(clear_values); + render_pass_info.pClearValues = clear_values; vkCmdBeginRenderPass(CMND.buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); @@ -1280,13 +1382,8 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) vkCmdBindDescriptorSets(CMND.buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PPLN.layout, 0, 1, &UBOD.set, 0, NULL); - // 6 is the number of vertices - // TODO: fix this -// #ifndef MONKEY - // vkCmdDrawIndexed(CMND.buffer, 6, 1, 0, 0, 0); -// #else - vkCmdDraw(CMND.buffer, 8723, 1, 0, 0); // draw monkey -// #endif + // vkCmdDrawIndexed(CMND.buffer, nvertices, 1, 0, 0, 0); + vkCmdDraw(CMND.buffer, nvertices, 1, 0, 0); // draw monkey // Cleaning up vkCmdEndRenderPass(CMND.buffer); @@ -1342,7 +1439,7 @@ static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding return 0; } -static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx) +static int memory_find_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx) { VkPhysicalDeviceMemoryProperties properties; vkGetPhysicalDeviceMemoryProperties(device, &properties); @@ -1358,6 +1455,55 @@ static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkM return 1; } +static int image_view_create(graphics_t graphics, VkFormat format, VkImageAspectFlags aspect_flags, VkImage image, VkImageView *image_view) +{ + int ret = 1; + + VkImageViewCreateInfo create_info = {0}; + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.image = image; + + create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info.format = format; + + // create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + // create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + // create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + // create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + + create_info.subresourceRange.aspectMask = aspect_flags; + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.levelCount = 1; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.layerCount = 1; + + VCHECK(vkCreateImageView, graphics->logical_device, &create_info, NULL, image_view); + + ret = 0; +exit: + return ret; +} + +static int image_format_filter(VkPhysicalDevice device, VkFormat *candidates, size_t ncandidates, VkImageTiling tiling, VkFormatFeatureFlags features, VkFormat *format) +{ + for(size_t i = 0; i < ncandidates; i++) { + VkFormatProperties props; + vkGetPhysicalDeviceFormatProperties(device, candidates[i], &props); + + if((tiling == VK_IMAGE_TILING_LINEAR) && + ((props.linearTilingFeatures & features) == features)) { + *format = candidates[i]; + return 0; + } else if((tiling == VK_IMAGE_TILING_OPTIMAL) && + ((props.optimalTilingFeatures & features) == features)) { + *format = candidates[i]; + return 0; + } + } + + return 1; +} + #define X_VK_RESULT_TABLE(X) \ X(VK_SUCCESS) \ X(VK_NOT_READY) \ |