diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/render.c | 364 | ||||
-rw-r--r-- | src/state.h | 2 | ||||
-rw-r--r-- | src/vksetup.h | 238 |
3 files changed, 341 insertions, 263 deletions
diff --git a/src/render.c b/src/render.c index 2ab38e1..810db51 100644 --- a/src/render.c +++ b/src/render.c @@ -355,7 +355,6 @@ vulkan_is_device_suitable(VkPhysicalDevice device) swapChainAdequate = !(swapChainSupport.formatCount == 0) && !(swapChainSupport.presentModeCount == 0); } - VkPhysicalDeviceFeatures supportedFeatures; vkGetPhysicalDeviceFeatures(device, &supportedFeatures); @@ -465,7 +464,7 @@ vulkan_create_logical_device() } vk_log(VK_INFO, "Vulkan logical device created\n"); - vkGetDeviceQueue(s.vk.device, indices.graphicsAndComputeFamily, 0, &s.vk_graphics_queue); + vkGetDeviceQueue(s.vk.device, indices.graphicsAndComputeFamily, 0, &s.vk_graphics_and_compute_queue); vkGetDeviceQueue(s.vk.device, indices.presentFamily, 0, &s.vk_present_queue); } @@ -639,7 +638,7 @@ create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags VkImageView imageView; VK_CHECK(vkCreateImageView(s.vk.device, &viewInfo, NULL, &imageView)); - + return imageView; } @@ -736,42 +735,6 @@ findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) return 9999; } -void -createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkFormat format, - VkImageTiling tiling, VkImageUsageFlags usage, - VkMemoryPropertyFlags properties, VkImage *image, - VkDeviceMemory *imageMemory, VkSampleCountFlagBits numSamples) -{ - VkImageCreateInfo imageInfo = {0}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent.width = width; - imageInfo.extent.height = height; - imageInfo.extent.depth = 1; - imageInfo.mipLevels = mipLevels; - imageInfo.arrayLayers = 1; - imageInfo.format = format; - imageInfo.tiling = tiling; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageInfo.usage = usage; - imageInfo.samples = numSamples; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK(vkCreateImage(s.vk.device, &imageInfo, NULL, image)); - - VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(s.vk.device, *image, &memRequirements); - - VkMemoryAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - - VK_CHECK(vkAllocateMemory(s.vk.device, &allocInfo, NULL, imageMemory)); - - vkBindImageMemory(s.vk.device, *image, *imageMemory , 0); -} - VkCommandBuffer beginSingleTimeCommands() { @@ -803,61 +766,12 @@ endSingleTimeCommands(VkCommandBuffer commandBuffer) submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; - VK_CHECK(vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK(vkQueueWaitIdle(s.vk_graphics_queue)); + VK_CHECK(vkQueueSubmit(s.vk_graphics_and_compute_queue, 1, &submitInfo, VK_NULL_HANDLE)); + VK_CHECK(vkQueueWaitIdle(s.vk_graphics_and_compute_queue)); vkFreeCommandBuffers(s.vk.device, s.vk_command_pool, 1, &commandBuffer); } -int -hasStencilComponent(VkFormat format) -{ - return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; -} - -void -transitionImageLayout(VkImage image, VkFormat format, - VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, - VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, - VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels) -{ - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkImageMemoryBarrier barrier = {0}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - - // barrier.subresourceRange.aspectMask = - if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - if (hasStencilComponent(format)) { - barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - } else { - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = mipLevels; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier(commandBuffer, - srcStageMask, dstStageMask, - 0, - 0, NULL, - 0, NULL, - 1, &barrier); - endSingleTimeCommands(commandBuffer); -} - VkFormat findSupportedFormat(VkFormat *candidates, size_t n, VkImageTiling tiling, @@ -891,19 +805,31 @@ findDepthFormat() void vulkan_create_depth_resources() { - VkFormat depthFormat = findDepthFormat(); + VkFormat depth_format = findDepthFormat(); vks_create_image(s.vk, s.vk.swapchain.extent.width, s.vk.swapchain.extent.height, 1, - depthFormat, VK_IMAGE_TILING_OPTIMAL, + depth_format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, s.msaa_samples, &s.depth_image); - s.depth_image.view = create_image_view(s.depth_image.handle, depthFormat, + s.depth_image.view = create_image_view(s.depth_image.handle, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT, 1); - transitionImageLayout(s.depth_image.handle, depthFormat, - VK_ACCESS_NONE, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1); + vks_transition_image_layout_info transition_info = { 0 }; + transition_info.cmd_info.vk = s.vk; + transition_info.cmd_info.pool = s.vk_command_pool; + transition_info.cmd_info.queue = s.vk_graphics_and_compute_queue; + transition_info.image = s.depth_image.handle; + transition_info.format = depth_format; + transition_info.srcAccessMask = VK_ACCESS_NONE; + transition_info.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + transition_info.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + transition_info.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + transition_info.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + transition_info.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + transition_info.mipLevels = 1; + + vks_transition_image_layout(&transition_info); } void vulkan_create_color_resources() { @@ -1179,12 +1105,23 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) vkCmdSetDepthWriteEnable(commandBuffer, 1); // TODO Make polygon mode dynamic //vkCmdSetPolygonModeEXT(commandBuffer, s.polygon_mode); - - transitionImageLayout( - s.vk.swapchain.images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1); + + vks_transition_image_layout_info transition_info = { 0 }; + + transition_info.cmd_info.vk = s.vk; + transition_info.cmd_info.pool = s.vk_command_pool; + transition_info.cmd_info.queue = s.vk_graphics_and_compute_queue; + transition_info.image = s.vk.swapchain.images[imageIndex]; + transition_info.format = VK_FORMAT_R8G8B8A8_SRGB; + transition_info.srcAccessMask = 0; + transition_info.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + transition_info.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + transition_info.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + transition_info.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + transition_info.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + transition_info.mipLevels = 1; + + vks_transition_image_layout(&transition_info); VkRenderingAttachmentInfo colorAttachment = {0}; colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; @@ -1243,17 +1180,18 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) s.graphics_pipeline.layout, 0, 1, &s.frames[currentFrame].vk_descriptor_set, 0, NULL); - - vkCmdDrawIndexed(commandBuffer, s.indices_count, 1, 0, 0, 0); + + vkCmdDrawIndexed(commandBuffer, s.indices_count, 1, 0, 0, 0); vkCmdEndRendering(commandBuffer); - transitionImageLayout(s.vk.swapchain.images[imageIndex], - VK_FORMAT_R8G8B8A8_SRGB, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1); + transition_info.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + transition_info.dstAccessMask = 0; + transition_info.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + transition_info.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + transition_info.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + transition_info.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + vks_transition_image_layout(&transition_info); VK_CHECK(vkEndCommandBuffer(commandBuffer)); } @@ -1275,16 +1213,6 @@ vulkan_create_sync_objects() } } -void copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - VkBufferCopy copyRegion = {0}; - copyRegion.srcOffset = 0; // Optional - copyRegion.dstOffset = 0; // Optional - copyRegion.size = size; - vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); - endSingleTimeCommands(commandBuffer); -} - void vulkan_create_vertex_buffer() { @@ -1309,7 +1237,8 @@ vulkan_create_vertex_buffer() VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vertex_buffer); - copy_buffer(stagingBuffer.handle, s.vertex_buffer.handle, bufferSize); + vks_command_info cmd_info = {s.vk, s.vk_command_pool, s.vk_graphics_and_compute_queue}; + vks_copy_buffer(&cmd_info, stagingBuffer.handle, s.vertex_buffer.handle, bufferSize); vkDestroyBuffer(s.vk.device, stagingBuffer.handle, NULL); vkFreeMemory(s.vk.device, stagingBuffer.memory, NULL); @@ -1339,7 +1268,8 @@ vulkan_create_index_buffer() VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.index_buffer); - copy_buffer(stagingBuffer.handle, s.index_buffer.handle, bufferSize); + vks_command_info cmd_info = {s.vk, s.vk_command_pool, s.vk_graphics_and_compute_queue}; + vks_copy_buffer(&cmd_info, stagingBuffer.handle, s.index_buffer.handle, bufferSize); vkDestroyBuffer(s.vk.device, stagingBuffer.handle, NULL); vkFreeMemory(s.vk.device, stagingBuffer.memory, NULL); @@ -1364,7 +1294,7 @@ vulkan_create_descriptor_set_layout() samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; VkDescriptorSetLayoutBinding bindings[2] = {uboLayoutBinding, samplerLayoutBinding}; - + VkDescriptorSetLayoutCreateInfo layoutInfo = {0}; layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.bindingCount = VK_ARRAY_LEN(bindings); @@ -1599,7 +1529,7 @@ handle_input(bool * quit) toggle = 0; } else { toggle = 1; - load_model_gltf(); + load_model_gltf(); } vkDestroyBuffer(s.vk.device, s.vertex_buffer.handle, NULL); vkFreeMemory(s.vk.device, s.vertex_buffer.memory, NULL); @@ -1652,7 +1582,7 @@ handle_input(bool * quit) } else { s.middle_click = 1; } - + } else if (e.type == SDL_MOUSEBUTTONUP) { if (e.button.button != 2) { @@ -1666,109 +1596,6 @@ handle_input(bool * quit) } void -copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, - uint32_t height) -{ - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkBufferImageCopy region = {0}; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - - region.imageOffset = (VkOffset3D){0, 0, 0}; - region.imageExtent = (VkExtent3D){width, height, 1}; - - vkCmdCopyBufferToImage(commandBuffer, - buffer, - image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ®ion - ); - - endSingleTimeCommands(commandBuffer); -} - -void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) { - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - - VkImageMemoryBarrier barrier = {0}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.image = image; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - barrier.subresourceRange.levelCount = 1; - - int32_t mipWidth = texWidth; - int32_t mipHeight = texHeight; - - for (uint32_t i = 1; i < mipLevels; i++) { - barrier.subresourceRange.baseMipLevel = i - 1; - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, - &barrier); - - VkImageBlit blit = {0}; - blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 }; - blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 }; - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.mipLevel = i - 1; - blit.srcSubresource.baseArrayLayer = 0; - blit.srcSubresource.layerCount = 1; - blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 }; - blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.mipLevel = i; - blit.dstSubresource.baseArrayLayer = 0; - blit.dstSubresource.layerCount = 1; - - vkCmdBlitImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, - VK_FILTER_LINEAR); - - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, - NULL, 1, &barrier); - - if (mipWidth > 1) mipWidth /= 2; - if (mipHeight > 1) mipHeight /= 2; - } - - /* barrier.subresourceRange.baseMipLevel = mipLevels - 1; */ - /* barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; */ - /* barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; */ - /* barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; */ - /* barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; */ - - /* vkCmdPipelineBarrier(commandBuffer, */ - /* VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, */ - /* 0, NULL, */ - /* 0, NULL, */ - /* 1, &barrier); */ - - endSingleTimeCommands(commandBuffer); -} - -void vulkan_create_texture_image() { int texWidth, texHeight, texChannels; @@ -1796,20 +1623,40 @@ vulkan_create_texture_image() VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_SAMPLE_COUNT_1_BIT, &s.texture_image); - transitionImageLayout( - s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, s.vk_mip_levels); - copyBufferToImage(stagingBuffer.handle, s.texture_image.handle, (uint32_t)texWidth, - (uint32_t)texHeight); - generateMipmaps(s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, s.vk_mip_levels); - transitionImageLayout( - s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, s.vk_mip_levels); + vks_command_info cmd_info = {0}; + cmd_info.vk = s.vk; + cmd_info.pool = s.vk_command_pool; + cmd_info.queue = s.vk_graphics_and_compute_queue; + + vks_transition_image_layout_info transition_info = { 0 }; + transition_info.cmd_info = cmd_info; + transition_info.image = s.texture_image.handle; + transition_info.format = VK_FORMAT_R8G8B8A8_SRGB; + transition_info.srcAccessMask = 0; + transition_info.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + transition_info.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + transition_info.dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; + transition_info.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + transition_info.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + transition_info.mipLevels = s.vk_mip_levels; + + vks_transition_image_layout(&transition_info); + + vks_copy_buffer_to_image(&cmd_info, + stagingBuffer.handle, + s.texture_image.handle, + (uint32_t)texWidth, + (uint32_t)texHeight); + vks_generate_mipmaps(&cmd_info, s.texture_image.handle, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, s.vk_mip_levels); + + transition_info.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + transition_info.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + transition_info.srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; + transition_info.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + transition_info.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + transition_info.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + vks_transition_image_layout(&transition_info); vkDestroyBuffer(s.vk.device, stagingBuffer.handle, NULL); vkFreeMemory(s.vk.device, stagingBuffer.memory, NULL); @@ -1890,7 +1737,7 @@ load_model_obj() } } s.indices[c] = mip; - + if (!index_seen) { int index = mi.p - 1; /* zero indexed */ if (mi.p) { @@ -1918,7 +1765,7 @@ load_model_obj() vk_log(VK_INFO, "[obj] %s: Loaded %ld vertices %ld indices\n", s.model_path, s.vertices_count, s.indices_count); - + fast_obj_destroy(m); } @@ -1935,7 +1782,7 @@ void load_model_gltf() { result = cgltf_load_buffers(&options, data, path); else { vk_log(VK_ERROR, "Can't load %s\n", path); - } + } if (result == cgltf_result_success) result = cgltf_validate(data); @@ -2024,7 +1871,7 @@ void vulkan_create_compute_stuff() srand((unsigned int)time(NULL)); - + Particle particles[PARTICLE_COUNT]; int width, height; SDL_GetWindowSize(s.vk.window, &width, &height); @@ -2061,10 +1908,11 @@ void vulkan_create_compute_stuff() memcpy(data, particles, (size_t)bufferSize); vkUnmapMemory(s.vk.device, stagingBuffer.memory); + vks_command_info cmd_info = {s.vk, s.vk_command_pool, s.vk_graphics_and_compute_queue}; for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vks_create_buffer(s.vk, bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.frames[i].shader_storage_buffer); // Copy data from the staging buffer (host) to the shader storage buffer (GPU) - copy_buffer(stagingBuffer.handle, s.frames[i].shader_storage_buffer.handle, bufferSize); + vks_copy_buffer(&cmd_info, stagingBuffer.handle, s.frames[i].shader_storage_buffer.handle, bufferSize); } VkDescriptorSetLayoutBinding layoutBindings[3]; @@ -2101,20 +1949,20 @@ void vulkan_create_compute_stuff() pipelineInfo.stage = computeShaderStageInfo; VK_CHECK(vkCreateComputePipelines(s.vk.device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &s.vk_compute_pipeline)); - + VkPipelineLayoutCreateInfo pipelineLayoutInfo = {0}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = 1; pipelineLayoutInfo.pSetLayouts = &s.vk_compute_descriptor_set_layout; VK_CHECK(vkCreatePipelineLayout(s.vk.device, &pipelineLayoutInfo, NULL, &s.vk_compute_pipeline_layout)); - + if (s.prev_comp_result != comp_result) { shaderc_result_release(comp_result); } vkDestroyShaderModule(s.vk.device, compShaderModule, NULL); - + } void @@ -2236,7 +2084,7 @@ updateUniformBuffer(uint32_t currentImage, float dt) ubo.resolution[0] = s.vk.swapchain.extent.width; ubo.resolution[1] = s.vk.swapchain.extent.height; - + //glm_mat4_identity(ubo.model); glm_mat4_dup(s.ubo.model, ubo.model); @@ -2253,7 +2101,7 @@ updateUniformBuffer(uint32_t currentImage, float dt) glm_lookat(s.camera.pos, s.camera.front, s.camera.up, ubo.view); /* glm_lookat(eye, center, GLM_ZUP, ubo.view); */ - + float aspect = s.vk.swapchain.extent.width / (float)s.vk.swapchain.extent.height; glm_perspective(glm_rad(45.0f + s.zoom ), aspect, 0.1f, 100.0f, ubo.proj); @@ -2269,7 +2117,7 @@ draw_frame() { float time = current_time(); float dt = time - prev_time; - + vkWaitForFences(s.vk.device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX); @@ -2305,9 +2153,7 @@ draw_frame() { submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &s.frames[currentFrame].render_finished_semaphore; - if (vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, s.frames[currentFrame].in_flight_fence) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to submit draw command buffer!\n"); - } + VK_CHECK(vkQueueSubmit(s.vk_graphics_and_compute_queue, 1, &submitInfo, s.frames[currentFrame].in_flight_fence)); VkSwapchainKHR swapChains[] = {s.vk.swapchain.handle}; VkPresentInfoKHR presentInfo = {0}; @@ -2329,7 +2175,7 @@ draw_frame() { } currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - + prev_time = time; } diff --git a/src/state.h b/src/state.h index 28f49e6..b9c9921 100644 --- a/src/state.h +++ b/src/state.h @@ -99,7 +99,7 @@ typedef struct state { vks_context vk; - VkQueue vk_graphics_queue; + VkQueue vk_graphics_and_compute_queue; VkQueue vk_present_queue; VkDescriptorSetLayout vk_descriptor_set_layout; diff --git a/src/vksetup.h b/src/vksetup.h index 4f05347..e78b887 100644 --- a/src/vksetup.h +++ b/src/vksetup.h @@ -196,11 +196,40 @@ typedef struct vks_frame_data { VkDescriptorSet vk_descriptor_set; } vks_frame_data; +/* Info structs */ +typedef struct vks_command_info +{ + vks_context vk; + VkCommandPool pool; + VkQueue queue; +} vks_command_info; + +typedef struct vks_transition_image_layout_info +{ + /* command */ + vks_command_info cmd_info; + /* image */ + VkImage image; + VkFormat format; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t mipLevels; +} vks_transition_image_layout_info; + /* Exported API */ -VKSDEF VkInstance vks_create_instance(bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window); -VKSDEF void vks_create_buffer(const vks_context vk, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags properties, vks_buffer *buffer); -VKSDEF void vks_create_image(const vks_context vk, const uint32_t width, const uint32_t height, const uint32_t mipLevels, const VkFormat format, const VkImageTiling tiling, const VkImageUsageFlags usage, const VkMemoryPropertyFlags properties, const VkSampleCountFlagBits numSamples, vks_image *image); +VKSDEF VkInstance vks_create_instance (bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window); +VKSDEF void vks_create_buffer (const vks_context vk, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags properties, vks_buffer *buffer); +VKSDEF void vks_create_image (const vks_context vk, const uint32_t width, const uint32_t height, const uint32_t mipLevels, const VkFormat format, const VkImageTiling tiling, const VkImageUsageFlags usage, const VkMemoryPropertyFlags properties, const VkSampleCountFlagBits numSamples, vks_image *image); +VKSDEF void vks_transition_image_layout (const vks_transition_image_layout_info *info); +VKSDEF void vks_copy_buffer (const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size); +VKSDEF void vks_copy_buffer_to_image (const vks_command_info* cmd_info, const VkBuffer buffer, VkImage image, const uint32_t width, const uint32_t height); +VKSDEF void vks_generate_mipmaps (const vks_command_info* cmd_info, VkImage image, const VkFormat imageFormat, const int32_t texWidth, const int32_t texHeight, const uint32_t mipLevels); + /* VKSDEF void vulkan_create_surface(); */ /* VKSDEF void vulkan_pick_physical_device(); */ /* VKSDEF void vulkan_create_logical_device(); */ @@ -279,8 +308,211 @@ find_memory_type(const vks_context vk, return 9999; } +VkCommandBuffer +begin_single_time_commands(const vks_command_info *info) +{ + VkCommandBufferAllocateInfo allocInfo = {0}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandPool = info->pool; + allocInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer; + VK_CHECK(vkAllocateCommandBuffers(info->vk.device, &allocInfo, &commandBuffer)); + + VkCommandBufferBeginInfo beginInfo = {0}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); + + return commandBuffer; +} + +void +end_single_time_commands(const vks_command_info *info, VkCommandBuffer command_buffer) +{ + VK_CHECK(vkEndCommandBuffer(command_buffer)); + + VkSubmitInfo submitInfo = {0}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &command_buffer; + + VK_CHECK(vkQueueSubmit(info->queue, 1, &submitInfo, VK_NULL_HANDLE)); + VK_CHECK(vkQueueWaitIdle(info->queue)); + + vkFreeCommandBuffers(info->vk.device, info->pool, 1, &command_buffer); +} + +int +has_stencil_component(VkFormat format) +{ + return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; +} + /* Vks API implementation */ VKSDEF void +vks_generate_mipmaps(const vks_command_info* cmd_info, + VkImage image, + const VkFormat imageFormat, + const int32_t texWidth, + const int32_t texHeight, + const uint32_t mipLevels) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info); + + VkImageMemoryBarrier barrier = {0}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.levelCount = 1; + + int32_t mipWidth = texWidth; + int32_t mipHeight = texHeight; + + for (uint32_t i = 1; i < mipLevels; i++) { + barrier.subresourceRange.baseMipLevel = i - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, + &barrier); + + VkImageBlit blit = {0}; + blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 }; + blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 }; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 }; + blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + + vkCmdBlitImage(command_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, + VK_FILTER_LINEAR); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, + NULL, 1, &barrier); + + if (mipWidth > 1) mipWidth /= 2; + if (mipHeight > 1) mipHeight /= 2; + } + + end_single_time_commands(cmd_info, command_buffer); +} + +VKSDEF void +vks_copy_buffer_to_image(const vks_command_info* cmd_info, + const VkBuffer buffer, + VkImage image, + const uint32_t width, + const uint32_t height) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info); + + VkBufferImageCopy region = {0}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + + region.imageOffset = (VkOffset3D){0, 0, 0}; + region.imageExtent = (VkExtent3D){width, height, 1}; + + vkCmdCopyBufferToImage(command_buffer, + buffer, + image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ®ion + ); + + end_single_time_commands(cmd_info, command_buffer); +} + +VKSDEF void +vks_copy_buffer(const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info); + + VkBufferCopy copy_region = {0}; + copy_region.srcOffset = 0; // Optional + copy_region.dstOffset = 0; // Optional + copy_region.size = size; + vkCmdCopyBuffer(command_buffer, src_buffer, dst_buffer, 1, ©_region); + + end_single_time_commands(cmd_info, command_buffer); +} + +VKSDEF void +vks_transition_image_layout(const vks_transition_image_layout_info *info) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(&info->cmd_info); + + VkImageMemoryBarrier barrier = { 0 }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcAccessMask = info->srcAccessMask; + barrier.dstAccessMask = info->dstAccessMask; + barrier.oldLayout = info->oldLayout; + barrier.newLayout = info->newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = info->image; + + // barrier.subresourceRange.aspectMask = + if (info->newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + + if (has_stencil_component(info->format)) { + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + } else { + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = info->mipLevels; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + + vkCmdPipelineBarrier(command_buffer, + info->srcStageMask, + info->dstStageMask, + 0, + 0, + NULL, + 0, + NULL, + 1, + &barrier); + + end_single_time_commands(&info->cmd_info, command_buffer); +} + +VKSDEF void vks_create_image(const vks_context vk, const uint32_t width, const uint32_t height, |