diff --git a/config/visual-studio/renderer.vcxproj b/config/visual-studio/renderer.vcxproj index def2f7f..0d592d3 100644 --- a/config/visual-studio/renderer.vcxproj +++ b/config/visual-studio/renderer.vcxproj @@ -132,14 +132,12 @@ - - diff --git a/config/visual-studio/renderer.vcxproj.filters b/config/visual-studio/renderer.vcxproj.filters index 4e0a0bc..573c97b 100644 --- a/config/visual-studio/renderer.vcxproj.filters +++ b/config/visual-studio/renderer.vcxproj.filters @@ -95,9 +95,6 @@ Source Files - - Source Files - Source Files @@ -154,9 +151,6 @@ Source Files - - Source Files - Source Files diff --git a/src/engine/renderer/tr_backend.c b/src/engine/renderer/tr_backend.c index 759fe47..ce26b84 100644 --- a/src/engine/renderer/tr_backend.c +++ b/src/engine/renderer/tr_backend.c @@ -21,10 +21,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "tr_local.h" -// VULKAN -#include "vk.h" -#include "vk_utils.h" - backEndData_t *backEndData[SMP_FRAMES]; backEndState_t backEnd; @@ -740,8 +736,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * Vk_Image& vk_image = tr.vk_resources.images[tr.scratchImage[client]->index]; vkDestroyImage(vk.device, vk_image.image, nullptr); vkDestroyImageView(vk.device, vk_image.image_view, nullptr); - vk_image.image = vk_create_cinematic_image(cols, rows, vk_image.staging_buffer); - vk_image.image_view = create_image_view(vk_image.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + vk_image.image = vk_create_cinematic_image(cols, rows, vk_image.staging_buffer, vk_image.image_view); vk_update_cinematic_image(vk_image.image, vk_image.staging_buffer, cols, rows, data); VkDescriptorImageInfo image_info; diff --git a/src/engine/renderer/tr_image.c b/src/engine/renderer/tr_image.c index 2f36691..3790a28 100644 --- a/src/engine/renderer/tr_image.c +++ b/src/engine/renderer/tr_image.c @@ -777,7 +777,7 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height // VULKAN Vk_Image& vk_image = tr.vk_resources.images[image->index]; - vk_image.image = vk_create_texture(pic, 4, width, height, vk_image.image_view); + vk_image.image = vk_create_texture(pic, width, height, vk_image.image_view); vk_image.descriptor_set = vk_create_descriptor_set(vk_image.image_view); return image; diff --git a/src/engine/renderer/vk.cpp b/src/engine/renderer/vk.cpp index c21e95c..53096e6 100644 --- a/src/engine/renderer/vk.cpp +++ b/src/engine/renderer/vk.cpp @@ -1,10 +1,10 @@ #include "tr_local.h" -#include "vk_utils.h" #include "vk_allocator.h" #include #include +#include FILE* vk_log_file; @@ -50,7 +50,8 @@ static VkFormat find_format_with_features(VkPhysicalDevice physical_device, cons if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features) return format; } - error("failed to find format with requested features"); + + ri.Error(ERR_FATAL, "Vulkan error: failed to find format with requested features"); return VK_FORMAT_UNDEFINED; // never get here } @@ -69,28 +70,26 @@ static uint32_t select_queue_family(VkPhysicalDevice physical_device, VkSurfaceK // select queue family with presentation and graphics support for (uint32_t i = 0; i < queue_family_count; i++) { VkBool32 presentation_supported; - auto result = vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &presentation_supported); - check_vk_result(result, "vkGetPhysicalDeviceSurfaceSupportKHR"); + VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &presentation_supported)); if (presentation_supported && (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) return i; } - error("failed to find queue family"); + + ri.Error(ERR_FATAL, "Vulkan error: failed to find queue family"); return -1; } static VkInstance create_instance() { uint32_t count = 0; - VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); - check_vk_result(result, "vkEnumerateInstanceExtensionProperties"); + VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr)); std::vector extension_properties(count); - result = vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data()); - check_vk_result(result, "vkEnumerateInstanceExtensionProperties"); + VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data())); for (auto name : instance_extensions) { if (!is_extension_available(extension_properties, name)) - error(std::string("required instance extension is not available: ") + name); + ri.Error(ERR_FATAL, "Vulkan error: required instance extension is not available: %s", name); } VkInstanceCreateInfo desc; @@ -104,22 +103,19 @@ static VkInstance create_instance() { desc.ppEnabledExtensionNames = instance_extensions.data(); VkInstance instance; - result = vkCreateInstance(&desc, nullptr, &instance); - check_vk_result(result, "vkCreateInstance"); + VK_CHECK(vkCreateInstance(&desc, nullptr, &instance)); return instance; } static VkPhysicalDevice select_physical_device(VkInstance instance) { uint32_t count; - VkResult result = vkEnumeratePhysicalDevices(instance, &count, nullptr); - check_vk_result(result, "vkEnumeratePhysicalDevices"); + VK_CHECK(vkEnumeratePhysicalDevices(instance, &count, nullptr)); if (count == 0) - error("no physical device found"); + ri.Error(ERR_FATAL, "Vulkan error: no physical device found"); std::vector physical_devices(count); - result = vkEnumeratePhysicalDevices(instance, &count, physical_devices.data()); - check_vk_result(result, "vkEnumeratePhysicalDevices"); + VK_CHECK(vkEnumeratePhysicalDevices(instance, &count, physical_devices.data())); return physical_devices[0]; // just get the first one } @@ -132,23 +128,20 @@ static VkSurfaceKHR create_surface(VkInstance instance, HWND hwnd) { desc.hwnd = hwnd; VkSurfaceKHR surface; - VkResult result = vkCreateWin32SurfaceKHR(instance, &desc, nullptr, &surface); - check_vk_result(result, "vkCreateWin32SurfaceKHR"); + VK_CHECK(vkCreateWin32SurfaceKHR(instance, &desc, nullptr, &surface)); return surface; } static VkDevice create_device(VkPhysicalDevice physical_device, uint32_t queue_family_index) { uint32_t count = 0; - VkResult result = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &count, nullptr); - check_vk_result(result, "vkEnumerateDeviceExtensionProperties"); + VK_CHECK(vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &count, nullptr)); std::vector extension_properties(count); - result = vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &count, extension_properties.data()); - check_vk_result(result, "vkEnumerateDeviceExtensionProperties"); + VK_CHECK(vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &count, extension_properties.data())); for (auto name : device_extensions) { if (!is_extension_available(extension_properties, name)) - error(std::string("required device extension is not available: ") + name); + ri.Error(ERR_FATAL, "Vulkan error: required device extension is not available: %s", name); } const float priority = 1.0; @@ -173,20 +166,17 @@ static VkDevice create_device(VkPhysicalDevice physical_device, uint32_t queue_f device_desc.pEnabledFeatures = nullptr; VkDevice device; - result = vkCreateDevice(physical_device, &device_desc, nullptr, &device); - check_vk_result(result, "vkCreateDevice"); + VK_CHECK(vkCreateDevice(physical_device, &device_desc, nullptr, &device)); return device; } static VkSurfaceFormatKHR select_surface_format(VkPhysicalDevice physical_device, VkSurfaceKHR surface) { uint32_t format_count; - VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, nullptr); - check_vk_result(result, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, nullptr)); assert(format_count > 0); std::vector candidates(format_count); - result = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, candidates.data()); - check_vk_result(result, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, candidates.data())); // special case that means we can choose any format if (candidates.size() == 1 && candidates[0].format == VK_FORMAT_UNDEFINED) { @@ -200,8 +190,7 @@ static VkSurfaceFormatKHR select_surface_format(VkPhysicalDevice physical_device static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevice device, VkSurfaceKHR surface, VkSurfaceFormatKHR surface_format) { VkSurfaceCapabilitiesKHR surface_caps; - VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_caps); - check_vk_result(result, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_caps)); VkExtent2D image_extent = surface_caps.currentExtent; if (image_extent.width == 0xffffffff && image_extent.height == 0xffffffff) { @@ -211,16 +200,15 @@ static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevic // transfer destination usage is required by image clear operations if ((surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) - error("VK_IMAGE_USAGE_TRANSFER_DST_BIT is not supported by the swapchain"); + ri.Error(ERR_FATAL, "Vulkan error: VK_IMAGE_USAGE_TRANSFER_DST_BIT is not supported by the swapchain"); + VkImageUsageFlags image_usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; // determine present mode and swapchain image count uint32_t present_mode_count; - result = vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, nullptr); - check_vk_result(result, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, nullptr)); std::vector present_modes(present_mode_count); - result = vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, present_modes.data()); - check_vk_result(result, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, present_modes.data())); VkPresentModeKHR present_mode; uint32_t image_count; @@ -260,8 +248,7 @@ static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevic desc.oldSwapchain = VK_NULL_HANDLE; VkSwapchainKHR swapchain; - result = vkCreateSwapchainKHR(device, &desc, nullptr, &swapchain); - check_vk_result(result, "vkCreateSwapchainKHR"); + VK_CHECK(vkCreateSwapchainKHR(device, &desc, nullptr, &swapchain)); return swapchain; } @@ -319,11 +306,131 @@ static VkRenderPass create_render_pass(VkDevice device, VkFormat color_format, V desc.pDependencies = nullptr; VkRenderPass render_pass; - VkResult result = vkCreateRenderPass(device, &desc, nullptr, &render_pass); - check_vk_result(result, "vkCreateRenderPass"); + VK_CHECK(vkCreateRenderPass(device, &desc, nullptr, &render_pass)); return render_pass; } +static VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspect_flags) { + VkImageViewCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.image = image; + desc.viewType = VK_IMAGE_VIEW_TYPE_2D; + desc.format = format; + desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + desc.subresourceRange.aspectMask = aspect_flags; + desc.subresourceRange.baseMipLevel = 0; + desc.subresourceRange.levelCount = 1; + desc.subresourceRange.baseArrayLayer = 0; + desc.subresourceRange.layerCount = 1; + + VkImageView image_view; + VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &image_view)); + return image_view; +} + + +static void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::function recorder) { + + VkCommandBufferAllocateInfo alloc_info; + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.commandPool = command_pool; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandBufferCount = 1; + + VkCommandBuffer command_buffer; + VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &command_buffer)); + + VkCommandBufferBeginInfo begin_info; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.pNext = nullptr; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + begin_info.pInheritanceInfo = nullptr; + + VK_CHECK(vkBeginCommandBuffer(command_buffer, &begin_info)); + recorder(command_buffer); + VK_CHECK(vkEndCommandBuffer(command_buffer)); + + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = nullptr; + + VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE)); + VK_CHECK(vkQueueWaitIdle(queue)); + vkFreeCommandBuffers(vk.device, command_pool, 1, &command_buffer); +} + +static void record_image_layout_transition(VkCommandBuffer command_buffer, VkImage image, VkFormat format, + VkAccessFlags src_access_flags, VkImageLayout old_layout, VkAccessFlags dst_access_flags, VkImageLayout new_layout) { + + auto has_depth_component = [](VkFormat format) { + switch (format) { + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return true; + default: + return false; + } + }; + auto has_stencil_component = [](VkFormat format) { + switch (format) { + case VK_FORMAT_S8_UINT: + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return true; + default: + return false; + } + }; + + VkImageMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = src_access_flags; + barrier.dstAccessMask = dst_access_flags; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + + bool depth = has_depth_component(format); + bool stencil = has_stencil_component(format); + if (depth && stencil) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + else if (depth) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + else if (stencil) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + else + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, + 0, nullptr, 0, nullptr, 1, &barrier); +} + VkPipeline create_pipeline(const Vk_Pipeline_Desc&); bool vk_initialize(HWND hwnd) { @@ -343,14 +450,12 @@ bool vk_initialize(HWND hwnd) { g.swapchain = create_swapchain(g.physical_device, g.device, g.surface, g.surface_format); - VkResult result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &vk.swapchain_image_count, nullptr); - check_vk_result(result, "vkGetSwapchainImagesKHR"); + VK_CHECK(vkGetSwapchainImagesKHR(g.device, g.swapchain, &vk.swapchain_image_count, nullptr)); if (vk.swapchain_image_count > MAX_SWAPCHAIN_IMAGES) ri.Error( ERR_FATAL, "initialize_vulkan: swapchain image count (%d) exceeded limit (%d)", vk.swapchain_image_count, MAX_SWAPCHAIN_IMAGES ); - result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &vk.swapchain_image_count, g.swapchain_images); - check_vk_result(result, "vkGetSwapchainImagesKHR"); + VK_CHECK(vkGetSwapchainImagesKHR(g.device, g.swapchain, &vk.swapchain_image_count, g.swapchain_images)); for (std::size_t i = 0; i < vk.swapchain_image_count; i++) { VkImageViewCreateInfo desc; @@ -369,8 +474,7 @@ bool vk_initialize(HWND hwnd) { desc.subresourceRange.levelCount = 1; desc.subresourceRange.baseArrayLayer = 0; desc.subresourceRange.layerCount = 1; - result = vkCreateImageView(g.device, &desc, nullptr, &g.swapchain_image_views[i]); - check_vk_result(result, "vkCreateImageView"); + VK_CHECK(vkCreateImageView(g.device, &desc, nullptr, &g.swapchain_image_views[i])); } { @@ -380,8 +484,7 @@ bool vk_initialize(HWND hwnd) { desc.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; desc.queueFamilyIndex = vk.queue_family_index; - result = vkCreateCommandPool(g.device, &desc, nullptr, &vk.command_pool); - check_vk_result(result, "vkCreateCommandPool"); + VK_CHECK(vkCreateCommandPool(g.device, &desc, nullptr, &vk.command_pool)); } { @@ -391,15 +494,41 @@ bool vk_initialize(HWND hwnd) { alloc_info.commandPool = vk.command_pool; alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; alloc_info.commandBufferCount = 1; - result = vkAllocateCommandBuffers(vk.device, &alloc_info, &g.command_buffer); - check_vk_result(result, "vkAllocateCommandBuffers"); + VK_CHECK(vkAllocateCommandBuffers(vk.device, &alloc_info, &g.command_buffer)); } get_allocator()->initialize(vk.physical_device, vk.device); + // + // Depth attachment image. + // { VkFormat depth_format = find_depth_format(vk.physical_device); - vk.depth_image = create_depth_attachment_image(glConfig.vidWidth, glConfig.vidHeight, depth_format); + + VkImageCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.imageType = VK_IMAGE_TYPE_2D; + desc.format = depth_format; + desc.extent.width = glConfig.vidWidth; + desc.extent.height = glConfig.vidHeight; + desc.extent.depth = 1; + desc.mipLevels = 1; + desc.arrayLayers = 1; + desc.samples = VK_SAMPLE_COUNT_1_BIT; + desc.tiling = VK_IMAGE_TILING_OPTIMAL; + desc.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + desc.queueFamilyIndexCount = 0; + desc.pQueueFamilyIndices = nullptr; + desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &vk.depth_image)); + + VkDeviceMemory memory = get_allocator()->allocate_memory(vk.depth_image); + VK_CHECK(vkBindImageMemory(vk.device, vk.depth_image, memory, 0)); + vk.depth_image_view = create_image_view(vk.depth_image, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT); record_and_run_commands(vk.command_pool, vk.queue, [&depth_format](VkCommandBuffer command_buffer) { @@ -428,8 +557,7 @@ bool vk_initialize(HWND hwnd) { for (uint32_t i = 0; i < vk.swapchain_image_count; i++) { attachments[0] = vk.swapchain_image_views[i]; // set color attachment - VkResult result = vkCreateFramebuffer(vk.device, &desc, nullptr, &vk.framebuffers[i]); - check_vk_result(result, "vkCreateFramebuffer"); + VK_CHECK(vkCreateFramebuffer(vk.device, &desc, nullptr, &vk.framebuffers[i])); } } @@ -449,8 +577,7 @@ bool vk_initialize(HWND hwnd) { desc.poolSizeCount = 1; desc.pPoolSizes = &pool_size; - VkResult result = vkCreateDescriptorPool(vk.device, &desc, nullptr, &vk.descriptor_pool); - check_vk_result(result, "vkCreateDescriptorPool"); + VK_CHECK(vkCreateDescriptorPool(vk.device, &desc, nullptr, &vk.descriptor_pool)); } // @@ -471,8 +598,7 @@ bool vk_initialize(HWND hwnd) { desc.bindingCount = 1; desc.pBindings = &descriptor_binding; - VkResult result = vkCreateDescriptorSetLayout(vk.device, &desc, nullptr, &vk.set_layout); - check_vk_result(result, "vkCreateDescriptorSetLayout"); + VK_CHECK(vkCreateDescriptorSetLayout(vk.device, &desc, nullptr, &vk.set_layout)); } // @@ -495,8 +621,7 @@ bool vk_initialize(HWND hwnd) { desc.pushConstantRangeCount = 1; desc.pPushConstantRanges = &push_range; - VkResult result = vkCreatePipelineLayout(vk.device, &desc, nullptr, &vk.pipeline_layout); - check_vk_result(result, "vkCreatePipelineLayout"); + VK_CHECK(vkCreatePipelineLayout(vk.device, &desc, nullptr, &vk.pipeline_layout)); } // @@ -513,16 +638,13 @@ bool vk_initialize(HWND hwnd) { desc.queueFamilyIndexCount = 0; desc.pQueueFamilyIndices = nullptr; - VkResult result = vkCreateBuffer(vk.device, &desc, nullptr, &vk.vertex_buffer); - check_vk_result(result, "vkCreateBuffer"); + VK_CHECK(vkCreateBuffer(vk.device, &desc, nullptr, &vk.vertex_buffer)); vk.vertex_buffer_memory = get_allocator()->allocate_staging_memory(vk.vertex_buffer); - result = vkBindBufferMemory(vk.device, vk.vertex_buffer, vk.vertex_buffer_memory, 0); - check_vk_result(result, "vkBindBufferMemory"); + VK_CHECK(vkBindBufferMemory(vk.device, vk.vertex_buffer, vk.vertex_buffer_memory, 0)); void* data; - result = vkMapMemory(vk.device, vk.vertex_buffer_memory, 0, VERTEX_BUFFER_SIZE, 0, &data); - check_vk_result(result, "vkMapMemory"); + VK_CHECK(vkMapMemory(vk.device, vk.vertex_buffer_memory, 0, VERTEX_BUFFER_SIZE, 0, &data)); vk.vertex_buffer_ptr = (byte*)data; } { @@ -536,16 +658,13 @@ bool vk_initialize(HWND hwnd) { desc.queueFamilyIndexCount = 0; desc.pQueueFamilyIndices = nullptr; - VkResult result = vkCreateBuffer(vk.device, &desc, nullptr, &vk.index_buffer); - check_vk_result(result, "vkCreateBuffer"); + VK_CHECK(vkCreateBuffer(vk.device, &desc, nullptr, &vk.index_buffer)); vk.index_buffer_memory = get_allocator()->allocate_staging_memory(vk.index_buffer); - result = vkBindBufferMemory(vk.device, vk.index_buffer, vk.index_buffer_memory, 0); - check_vk_result(result, "vkBindBufferMemory"); + VK_CHECK(vkBindBufferMemory(vk.device, vk.index_buffer, vk.index_buffer_memory, 0)); void* data; - result = vkMapMemory(vk.device, vk.index_buffer_memory, 0, INDEX_BUFFER_SIZE, 0, &data); - check_vk_result(result, "vkMapMemory"); + VK_CHECK(vkMapMemory(vk.device, vk.index_buffer_memory, 0, INDEX_BUFFER_SIZE, 0, &data)); vk.index_buffer_ptr = (byte*)data; } @@ -558,17 +677,14 @@ bool vk_initialize(HWND hwnd) { desc.pNext = nullptr; desc.flags = 0; - VkResult result = vkCreateSemaphore(vk.device, &desc, nullptr, &vk.image_acquired); - check_vk_result(result, "vkCreateSemaphore"); - result = vkCreateSemaphore(vk.device, &desc, nullptr, &vk.rendering_finished); - check_vk_result(result, "vkCreateSemaphore"); + VK_CHECK(vkCreateSemaphore(vk.device, &desc, nullptr, &vk.image_acquired)); + VK_CHECK(vkCreateSemaphore(vk.device, &desc, nullptr, &vk.rendering_finished)); VkFenceCreateInfo fence_desc; fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_desc.pNext = nullptr; fence_desc.flags = VK_FENCE_CREATE_SIGNALED_BIT; - result = vkCreateFence(vk.device, &fence_desc, nullptr, &vk.rendering_finished_fence); - check_vk_result(result, "vkCreateFence"); + VK_CHECK(vkCreateFence(vk.device, &fence_desc, nullptr, &vk.rendering_finished_fence)); } // @@ -577,7 +693,7 @@ bool vk_initialize(HWND hwnd) { { auto create_shader_module = [](uint8_t* bytes, int count) { if (count % 4 != 0) { - error("SPIR-V binary buffer size is not multiple of 4"); + ri.Error(ERR_FATAL, "Vulkan error: SPIR-V binary buffer size is not multiple of 4"); } VkShaderModuleCreateInfo desc; desc.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; @@ -587,8 +703,7 @@ bool vk_initialize(HWND hwnd) { desc.pCode = reinterpret_cast(bytes); VkShaderModule module; - VkResult result = vkCreateShaderModule(vk.device, &desc, nullptr, &module); - check_vk_result(result, "vkCreateShaderModule"); + VK_CHECK(vkCreateShaderModule(vk.device, &desc, nullptr, &module)); return module; }; @@ -623,8 +738,7 @@ bool vk_initialize(HWND hwnd) { desc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; desc.unnormalizedCoordinates = VK_FALSE; - VkResult result = vkCreateSampler(vk.device, &desc, nullptr, &vk.sampler); - check_vk_result(result, "vkCreateSampler"); + VK_CHECK(vkCreateSampler(vk.device, &desc, nullptr, &vk.sampler)); } // @@ -693,54 +807,111 @@ void vk_deinitialize() { vk = Vulkan_Instance(); } -VkImage vk_create_texture(const uint8_t* pixels, int bytes_per_pixel, int image_width, int image_height, VkImageView& image_view) { - VkImage staging_image = create_staging_texture(image_width, image_height, - bytes_per_pixel == 3 ? VK_FORMAT_R8G8B8_UNORM : VK_FORMAT_R8G8B8A8_UNORM, pixels, bytes_per_pixel); +static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer, + VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages, + VkAccessFlags src_access, VkAccessFlags dst_access) { - VkImage texture_image = ::create_texture(image_width, image_height, - bytes_per_pixel == 3 ? VK_FORMAT_R8G8B8_UNORM : VK_FORMAT_R8G8B8A8_UNORM); + VkBufferMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;; + barrier.pNext = nullptr; + barrier.srcAccessMask = src_access; + barrier.dstAccessMask = dst_access; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = buffer; + barrier.offset = 0; + barrier.size = VK_WHOLE_SIZE; + vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr); +} + +VkImage vk_create_texture(const uint8_t* rgba_pixels, int image_width, int image_height, VkImageView& image_view) { + int image_size = image_width * image_height * 4; + + // create staging buffer + VkBufferCreateInfo buffer_desc; + buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_desc.pNext = nullptr; + buffer_desc.flags = 0; + buffer_desc.size = image_size; + buffer_desc.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_desc.queueFamilyIndexCount = 0; + buffer_desc.pQueueFamilyIndices = nullptr; + + VkBuffer staging_buffer; + VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &staging_buffer)); + + get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(staging_buffer); + VkDeviceMemory buffer_memory = get_allocator()->get_shared_staging_memory().get_handle(); + VK_CHECK(vkBindBufferMemory(vk.device, staging_buffer, buffer_memory, 0)); + + void* buffer_data; + VK_CHECK(vkMapMemory(vk.device, buffer_memory, 0, image_size, 0, &buffer_data)); + Com_Memcpy(buffer_data, rgba_pixels, image_size); + vkUnmapMemory(vk.device, buffer_memory); + + // create texture image + VkImageCreateInfo desc; + desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + desc.pNext = nullptr; + desc.flags = 0; + desc.imageType = VK_IMAGE_TYPE_2D; + desc.format = VK_FORMAT_R8G8B8A8_UNORM; + desc.extent.width = image_width; + desc.extent.height = image_height; + desc.extent.depth = 1; + desc.mipLevels = 1; + desc.arrayLayers = 1; + desc.samples = VK_SAMPLE_COUNT_1_BIT; + desc.tiling = VK_IMAGE_TILING_OPTIMAL; + desc.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + desc.queueFamilyIndexCount = 0; + desc.pQueueFamilyIndices = nullptr; + desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkImage texture_image; + VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &texture_image)); + + VkDeviceMemory memory = get_allocator()->allocate_memory(texture_image); + VK_CHECK(vkBindImageMemory(vk.device, texture_image, memory, 0)); + + // copy buffer's content to texture record_and_run_commands(vk.command_pool, vk.queue, - [&texture_image, &staging_image, &image_width, &image_height](VkCommandBuffer command_buffer) { + [&texture_image, &staging_buffer, &image_width, &image_height](VkCommandBuffer command_buffer) { - record_image_layout_transition(command_buffer, staging_image, VK_FORMAT_R8G8B8A8_UNORM, - VK_ACCESS_HOST_WRITE_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + record_buffer_memory_barrier(command_buffer, staging_buffer, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); record_image_layout_transition(command_buffer, texture_image, VK_FORMAT_R8G8B8A8_UNORM, 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - // copy staging image's data to device local image - VkImageSubresourceLayers subresource_layers; - subresource_layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_layers.mipLevel = 0; - subresource_layers.baseArrayLayer = 0; - subresource_layers.layerCount = 1; + VkBufferImageCopy region; + 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{ (uint32_t)image_width, (uint32_t)image_height, 1 }; - VkImageCopy region; - region.srcSubresource = subresource_layers; - region.srcOffset = {0, 0, 0}; - region.dstSubresource = subresource_layers; - region.dstOffset = {0, 0, 0}; - region.extent.width = image_width; - region.extent.height = image_height; - region.extent.depth = 1; - - vkCmdCopyImage(command_buffer, - staging_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - texture_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ®ion); + vkCmdCopyBufferToImage(command_buffer, staging_buffer, texture_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); record_image_layout_transition(command_buffer, texture_image, VK_FORMAT_R8G8B8A8_UNORM, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); }); - vkDestroyImage(vk.device, staging_image, nullptr); + vkDestroyBuffer(vk.device, staging_buffer, nullptr); image_view = create_image_view(texture_image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); return texture_image; } -VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer) { +VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer, VkImageView& image_view) { VkBufferCreateInfo buffer_desc; buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_desc.pNext = nullptr; @@ -752,12 +923,10 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag buffer_desc.pQueueFamilyIndices = nullptr; VkBuffer buffer; - VkResult result = vkCreateBuffer(vk.device, &buffer_desc, nullptr, &buffer); - check_vk_result(result, "vkCreateBuffer"); + VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &buffer)); VkDeviceMemory buffer_memory = get_allocator()->allocate_staging_memory(buffer); - result = vkBindBufferMemory(vk.device, buffer, buffer_memory, 0); - check_vk_result(result, "vkBindBufferMemory"); + VK_CHECK(vkBindBufferMemory(vk.device, buffer, buffer_memory, 0)); VkImageCreateInfo image_desc; image_desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -779,24 +948,24 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag image_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImage image; - result = vkCreateImage(vk.device, &image_desc, nullptr, &image); - check_vk_result(result, "vkCreateImage"); + VK_CHECK(vkCreateImage(vk.device, &image_desc, nullptr, &image)); VkDeviceMemory image_memory = get_allocator()->allocate_memory(image); - result = vkBindImageMemory(vk.device, image, image_memory, 0); - check_vk_result(result, "vkBindImageMemory"); + VK_CHECK(vkBindImageMemory(vk.device, image, image_memory, 0)); staging_buffer.handle = buffer; staging_buffer.memory = buffer_memory; staging_buffer.offset = 0; staging_buffer.size = width * height * 4; + + image_view = create_image_view(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + return image; } void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_buffer, int width, int height, const uint8_t* rgba_pixels) { void* buffer_data; - VkResult result = vkMapMemory(vk.device, staging_buffer.memory, staging_buffer.offset, staging_buffer.size, 0, &buffer_data); - check_vk_result(result, "vkMapMemory"); + VK_CHECK(vkMapMemory(vk.device, staging_buffer.memory, staging_buffer.offset, staging_buffer.size, 0, &buffer_data)); memcpy(buffer_data, rgba_pixels, staging_buffer.size); vkUnmapMemory(vk.device, staging_buffer.memory); @@ -1131,8 +1300,7 @@ static VkPipeline create_pipeline(const Vk_Pipeline_Desc& desc) { create_info.basePipelineIndex = -1; VkPipeline pipeline; - VkResult result = vkCreateGraphicsPipelines(vk.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline); - check_vk_result(result, "vkCreateGraphicsPipelines"); + VK_CHECK(vkCreateGraphicsPipelines(vk.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline)); return pipeline; } @@ -1180,8 +1348,7 @@ VkDescriptorSet vk_create_descriptor_set(VkImageView image_view) { desc.pSetLayouts = &vk.set_layout; VkDescriptorSet set; - VkResult result = vkAllocateDescriptorSets(vk.device, &desc, &set); - check_vk_result(result, "vkAllocateDescriptorSets"); + VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &set)); VkDescriptorImageInfo image_info; image_info.sampler = vk.sampler; @@ -1422,13 +1589,10 @@ void vk_begin_frame() { if (r_logFile->integer) fprintf(vk_log_file, "vk_begin_frame\n"); - VkResult result = vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vk.image_acquired, VK_NULL_HANDLE, &vk.swapchain_image_index); - check_vk_result(result, "vkAcquireNextImageKHR"); + VK_CHECK(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vk.image_acquired, VK_NULL_HANDLE, &vk.swapchain_image_index)); - result = vkWaitForFences(vk.device, 1, &vk.rendering_finished_fence, VK_FALSE, 1e9); - check_vk_result(result, "vkWaitForFences"); - result = vkResetFences(vk.device, 1, &vk.rendering_finished_fence); - check_vk_result(result, "vkResetFences"); + VK_CHECK(vkWaitForFences(vk.device, 1, &vk.rendering_finished_fence, VK_FALSE, 1e9)); + VK_CHECK(vkResetFences(vk.device, 1, &vk.rendering_finished_fence)); VkCommandBufferBeginInfo begin_info; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -1436,8 +1600,7 @@ void vk_begin_frame() { begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; begin_info.pInheritanceInfo = nullptr; - result = vkBeginCommandBuffer(vk.command_buffer, &begin_info); - check_vk_result(result, "vkBeginCommandBuffer"); + VK_CHECK(vkBeginCommandBuffer(vk.command_buffer, &begin_info)); VkClearValue clear_values[2]; /// ignore clear_values[0] which corresponds to color attachment @@ -1471,8 +1634,7 @@ void vk_end_frame() { vkCmdEndRenderPass(vk.command_buffer); - VkResult result = vkEndCommandBuffer(vk.command_buffer); - check_vk_result(result, "vkEndCommandBuffer"); + VK_CHECK(vkEndCommandBuffer(vk.command_buffer)); if (r_logFile->integer) { fprintf(vk_log_file, "present\n"); @@ -1491,8 +1653,7 @@ void vk_end_frame() { submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &vk.rendering_finished; - result = vkQueueSubmit(vk.queue, 1, &submit_info, vk.rendering_finished_fence); - check_vk_result(result, "vkQueueSubmit"); + VK_CHECK(vkQueueSubmit(vk.queue, 1, &submit_info, vk.rendering_finished_fence)); VkPresentInfoKHR present_info; present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; @@ -1503,6 +1664,5 @@ void vk_end_frame() { present_info.pSwapchains = &vk.swapchain; present_info.pImageIndices = &vk.swapchain_image_index; present_info.pResults = nullptr; - result = vkQueuePresentKHR(vk.queue, &present_info); - check_vk_result(result, "vkQueuePresentKHR"); + VK_CHECK(vkQueuePresentKHR(vk.queue, &present_info)); } diff --git a/src/engine/renderer/vk.h b/src/engine/renderer/vk.h index 27d373b..d5d109c 100644 --- a/src/engine/renderer/vk.h +++ b/src/engine/renderer/vk.h @@ -6,12 +6,17 @@ #endif #include "vulkan/vulkan.h" -#include "../../game/q_shared.h" const int MAX_SWAPCHAIN_IMAGES = 8; const int MAX_VK_PIPELINES = 1024; const int MAX_VK_IMAGES = 2048; // should be the same as MAX_DRAWIMAGES +#define VK_CHECK(function_call) { \ + VkResult result = function_call; \ + if (result < 0) \ + ri.Error(ERR_FATAL, "Vulkan error: function %s, error code %d", function_call, result); \ +} + enum class Vk_Shader_Type { single_texture, multi_texture_mul, @@ -56,8 +61,8 @@ bool vk_initialize(HWND hwnd); void vk_deinitialize(); void vk_destroy_resources(); -VkImage vk_create_texture(const uint8_t* pixels, int bytes_per_pixel, int width, int height, VkImageView& image_view); -VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer); +VkImage vk_create_texture(const uint8_t* rgba_pixels, int width, int height, VkImageView& image_view); +VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer, VkImageView& image_view); void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_buffer, int width, int height, const uint8_t* rgba_pixels); VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc); VkDescriptorSet vk_create_descriptor_set(VkImageView image_view); diff --git a/src/engine/renderer/vk_allocator.cpp b/src/engine/renderer/vk_allocator.cpp index 9862302..b92cd78 100644 --- a/src/engine/renderer/vk_allocator.cpp +++ b/src/engine/renderer/vk_allocator.cpp @@ -1,5 +1,5 @@ #include "vk_allocator.h" -#include "vk_utils.h" +#include "tr_local.h" static Device_Memory_Allocator allocator; @@ -17,7 +17,7 @@ static uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t memo return i; } } - error("failed to find matching memory type with requested properties"); + ri.Error(ERR_FATAL, "Vulkan error: failed to find matching memory type with requested properties"); return -1; } @@ -69,8 +69,7 @@ void Shared_Staging_Memory::ensure_allocation(const VkMemoryRequirements& memory alloc_info.allocationSize = memory_requirements.size; alloc_info.memoryTypeIndex = required_memory_type_index; - VkResult result = vkAllocateMemory(device, &alloc_info, nullptr, &handle); - check_vk_result(result, "vkAllocateMemory"); + VK_CHECK(vkAllocateMemory(device, &alloc_info, nullptr, &handle)); size = memory_requirements.size; memory_type_index = required_memory_type_index; } @@ -102,12 +101,6 @@ VkDeviceMemory Device_Memory_Allocator::allocate_memory(VkBuffer buffer) { return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); } -VkDeviceMemory Device_Memory_Allocator::allocate_staging_memory(VkImage image) { - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(device, image, &memory_requirements); - return allocate_memory(memory_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); -} - VkDeviceMemory Device_Memory_Allocator::allocate_staging_memory(VkBuffer buffer) { VkMemoryRequirements memory_requirements; vkGetBufferMemoryRequirements(device, buffer, &memory_requirements); @@ -126,8 +119,7 @@ VkDeviceMemory Device_Memory_Allocator::allocate_memory(const VkMemoryRequiremen alloc_info.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, properties); VkDeviceMemory chunk; - VkResult result = vkAllocateMemory(device, &alloc_info, nullptr, &chunk); - check_vk_result(result, "vkAllocateMemory"); + VK_CHECK(vkAllocateMemory(device, &alloc_info, nullptr, &chunk)); chunks.push_back(chunk); return chunk; } diff --git a/src/engine/renderer/vk_allocator.h b/src/engine/renderer/vk_allocator.h index eaf1c16..ffa7bc5 100644 --- a/src/engine/renderer/vk_allocator.h +++ b/src/engine/renderer/vk_allocator.h @@ -33,7 +33,6 @@ public: VkDeviceMemory allocate_memory(VkImage image); VkDeviceMemory allocate_memory(VkBuffer buffer); - VkDeviceMemory allocate_staging_memory(VkImage image); VkDeviceMemory allocate_staging_memory(VkBuffer buffer); Shared_Staging_Memory& get_shared_staging_memory(); diff --git a/src/engine/renderer/vk_utils.cpp b/src/engine/renderer/vk_utils.cpp deleted file mode 100644 index 1192e5c..0000000 --- a/src/engine/renderer/vk_utils.cpp +++ /dev/null @@ -1,258 +0,0 @@ -#include "vk_allocator.h" -#include "vk.h" -#include "vk_utils.h" -#include -#include - -#include "tr_local.h" - -void check_vk_result(VkResult result, const char* functionName) { - if (result < 0) { - error(functionName + std::string(" has returned error code with value ") + std::to_string(result)); - } -} - -void error(const std::string& message) { - std::cout << message << std::endl; - throw std::runtime_error(message); -} - -void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::function recorder) { - - VkCommandBufferAllocateInfo alloc_info; - alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.commandPool = command_pool; - alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - alloc_info.commandBufferCount = 1; - - VkCommandBuffer command_buffer; - VkResult result = vkAllocateCommandBuffers(vk.device, &alloc_info, &command_buffer); - check_vk_result(result, "vkAllocateCommandBuffers"); - - VkCommandBufferBeginInfo begin_info; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.pNext = nullptr; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - begin_info.pInheritanceInfo = nullptr; - - result = vkBeginCommandBuffer(command_buffer, &begin_info); - check_vk_result(result, "vkBeginCommandBuffer"); - recorder(command_buffer); - result = vkEndCommandBuffer(command_buffer); - check_vk_result(result, "vkEndCommandBuffer"); - - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = nullptr; - submit_info.pWaitDstStageMask = nullptr; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - - result = vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); - check_vk_result(result, "vkQueueSubmit"); - result = vkQueueWaitIdle(queue); - check_vk_result(result, "vkQueueWaitIdle"); - vkFreeCommandBuffers(vk.device, command_pool, 1, &command_buffer); -} - -static bool has_depth_component(VkFormat format) { - switch (format) { - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_X8_D24_UNORM_PACK32: - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - return true; - default: - return false; - } -} - -static bool has_stencil_component(VkFormat format) { - switch (format) { - case VK_FORMAT_S8_UINT: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - return true; - default: - return false; - } -} - -void record_image_layout_transition(VkCommandBuffer command_buffer, VkImage image, VkFormat format, - VkAccessFlags src_access_flags, VkImageLayout old_layout, VkAccessFlags dst_access_flags, VkImageLayout new_layout) { - - VkImageMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = src_access_flags; - barrier.dstAccessMask = dst_access_flags; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - - bool depth = has_depth_component(format); - bool stencil = has_stencil_component(format); - if (depth && stencil) - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - else if (depth) - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - else if (stencil) - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - else - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, - 0, nullptr, 0, nullptr, 1, &barrier); -} - -VkImage create_texture(int image_width, int image_height, VkFormat format) { - VkImageCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.imageType = VK_IMAGE_TYPE_2D; - desc.format = format; - desc.extent.width = image_width; - desc.extent.height = image_height; - desc.extent.depth = 1; - desc.mipLevels = 1; - desc.arrayLayers = 1; - desc.samples = VK_SAMPLE_COUNT_1_BIT; - desc.tiling = VK_IMAGE_TILING_OPTIMAL; - desc.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; - desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImage image; - VkResult result = vkCreateImage(vk.device, &desc, nullptr, &image); - check_vk_result(result, "vkCreateImage"); - - VkDeviceMemory memory = get_allocator()->allocate_memory(image); - result = vkBindImageMemory(vk.device, image, memory, 0); - check_vk_result(result, "vkBindImageMemory"); - return image; -} - -VkImage create_staging_texture(int image_width, int image_height, VkFormat format, const uint8_t* pixels, int bytes_per_pixel) { - VkImageCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.imageType = VK_IMAGE_TYPE_2D; - desc.format = format; - desc.extent.width = image_width; - desc.extent.height = image_height; - desc.extent.depth = 1; - desc.mipLevels = 1; - desc.arrayLayers = 1; - desc.samples = VK_SAMPLE_COUNT_1_BIT; - desc.tiling = VK_IMAGE_TILING_LINEAR; - desc.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; - desc.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - - VkImage image; - VkResult result = vkCreateImage(vk.device, &desc, nullptr, &image); - check_vk_result(result, "vkCreateImage"); - - get_allocator()->get_shared_staging_memory().ensure_allocation_for_object(image); - VkDeviceMemory memory = get_allocator()->get_shared_staging_memory().get_handle(); - result = vkBindImageMemory(vk.device, image, memory, 0); - check_vk_result(result, "vkBindImageMemory"); - - VkImageSubresource staging_image_subresource; - staging_image_subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - staging_image_subresource.mipLevel = 0; - staging_image_subresource.arrayLayer = 0; - VkSubresourceLayout staging_image_layout; - vkGetImageSubresourceLayout(vk.device, image, &staging_image_subresource, &staging_image_layout); - - void* data; - result = vkMapMemory(vk.device, memory, 0, staging_image_layout.size, 0, &data); - check_vk_result(result, "vkMapMemory"); - - const int bytes_per_row = image_width * bytes_per_pixel; - if (staging_image_layout.rowPitch == bytes_per_row) { - memcpy(data, pixels, bytes_per_row * image_height); - } else { - auto bytes = static_cast(data); - for (int i = 0; i < image_height; i++) { - memcpy(&bytes[i * staging_image_layout.rowPitch], &pixels[i * bytes_per_row], bytes_per_row); - } - } - vkUnmapMemory(vk.device, memory); - return image; -} - -VkImage create_depth_attachment_image(int image_width, int image_height, VkFormat format) { - VkImageCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.imageType = VK_IMAGE_TYPE_2D; - desc.format = format; - desc.extent.width = image_width; - desc.extent.height = image_height; - desc.extent.depth = 1; - desc.mipLevels = 1; - desc.arrayLayers = 1; - desc.samples = VK_SAMPLE_COUNT_1_BIT; - desc.tiling = VK_IMAGE_TILING_OPTIMAL; - desc.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - desc.queueFamilyIndexCount = 0; - desc.pQueueFamilyIndices = nullptr; - desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImage image; - VkResult result = vkCreateImage(vk.device, &desc, nullptr, &image); - check_vk_result(result, "vkCreateImage"); - - VkDeviceMemory memory = get_allocator()->allocate_memory(image); - result = vkBindImageMemory(vk.device, image, memory, 0); - check_vk_result(result, "vkBindImageMemory"); - return image; -} - -VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspect_flags) { - VkImageViewCreateInfo desc; - desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - desc.pNext = nullptr; - desc.flags = 0; - desc.image = image; - desc.viewType = VK_IMAGE_VIEW_TYPE_2D; - desc.format = format; - desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - desc.subresourceRange.aspectMask = aspect_flags; - desc.subresourceRange.baseMipLevel = 0; - desc.subresourceRange.levelCount = 1; - desc.subresourceRange.baseArrayLayer = 0; - desc.subresourceRange.layerCount = 1; - - VkImageView image_view; - VkResult result = vkCreateImageView(vk.device, &desc, nullptr, &image_view); - check_vk_result(result, "vkCreateImageView"); - return image_view; -} diff --git a/src/engine/renderer/vk_utils.h b/src/engine/renderer/vk_utils.h deleted file mode 100644 index f4f7738..0000000 --- a/src/engine/renderer/vk_utils.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "vk.h" -#include -#include - -// Errors -void check_vk_result(VkResult result, const char* function_name); -void error(const std::string& message); - -// Command buffers -void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, std::function recorder); - -void record_image_layout_transition( - VkCommandBuffer command_buffer, VkImage image, VkFormat format, - VkAccessFlags src_access_flags, VkImageLayout old_layout, - VkAccessFlags dst_access_flags, VkImageLayout new_layout); - -// Images -VkImage create_texture(int image_width, int image_height, VkFormat format); -VkImage create_staging_texture(int image_width, int image_height, VkFormat format, const uint8_t* pixels, int bytes_per_pixel); -VkImage create_depth_attachment_image(int image_width, int image_height, VkFormat format); -VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspect_flags);