summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/render.c364
-rw-r--r--src/state.h2
-rw-r--r--src/vksetup.h238
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, &copyRegion);
- 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,
- &region
- );
-
- 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,
+ &region
+ );
+
+ 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, &copy_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,