X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Ftexture_backend.cpp;h=168d6adb0501d69a501b83e8bb726a860fd8e978;hb=d2a23243b7f25e56ef098196b2962c103989143f;hp=ff1afad9b1130933136f4970992f700ce1245765;hpb=99ca354f18119f82f1adeca100cd665a8f640317;p=libs%2Fgl.git diff --git a/source/backends/vulkan/texture_backend.cpp b/source/backends/vulkan/texture_backend.cpp index ff1afad9..168d6adb 100644 --- a/source/backends/vulkan/texture_backend.cpp +++ b/source/backends/vulkan/texture_backend.cpp @@ -1,5 +1,6 @@ #include "device.h" #include "error.h" +#include "synchronizer.h" #include "texture.h" #include "texture_backend.h" #include "vulkan.h" @@ -18,17 +19,23 @@ VulkanTexture::VulkanTexture(VulkanTexture &&other): device(other.device), handle(other.handle), view_handle(other.view_handle), + memory_id(other.memory_id), view_type(other.view_type), debug_name(move(other.debug_name)) { other.handle = 0; other.view_handle = 0; + other.memory_id = 0; } VulkanTexture::~VulkanTexture() { + DestroyQueue &dq = device.get_destroy_queue(); + if(view_handle) - device.get_destroy_queue().destroy(view_handle); + dq.destroy(view_handle); + if(handle) + dq.destroy(handle, memory_id); } void VulkanTexture::allocate() @@ -36,14 +43,44 @@ void VulkanTexture::allocate() const Texture &self = *static_cast(this); const VulkanFunctions &vk = device.get_functions(); + VkImageCreateInfo image_info = { }; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.format = static_cast(get_vulkan_pixelformat(self.storage_fmt)); + image_info.extent.width = 1; + image_info.extent.height = 1; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT; + PixelComponents comp = get_components(self.storage_fmt); + if(comp==DEPTH_COMPONENT || comp==STENCIL_INDEX) + image_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + else + image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + fill_image_info(&image_info); + + /* SwapChainTexture may have already provided the image. Create_info is + filled anyway because some of its fields are used for view_info. */ if(!handle) - throw logic_error("Texture image allocation is unimplemented"); + { + vk.CreateImage(image_info, handle); + memory_id = device.get_allocator().allocate(handle, DEVICE_MEMORY); + + // Trigger a layout transition if the image is used before uploading data. + change_layout(0, -1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true); + } VkImageViewCreateInfo view_info = { }; view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; view_info.image = handle_cast<::VkImage>(handle); view_info.viewType = static_cast(view_type); - view_info.format = static_cast(get_vulkan_pixelformat(self.storage_fmt)); + view_info.format = image_info.format; const unsigned *swizzle_order = get_vulkan_swizzle(self.swizzle); view_info.components.r = static_cast(swizzle_order[0]); @@ -53,9 +90,9 @@ void VulkanTexture::allocate() view_info.subresourceRange.aspectMask = get_vulkan_aspect(get_components(self.storage_fmt)); view_info.subresourceRange.baseMipLevel = 0; - view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.levelCount = image_info.mipLevels; view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = 1; + view_info.subresourceRange.layerCount = image_info.arrayLayers; vk.CreateImageView(view_info, view_handle); @@ -63,9 +100,41 @@ void VulkanTexture::allocate() set_vulkan_object_names(); } -void VulkanTexture::generate_mipmap() +void VulkanTexture::generate_mipmap_levels(unsigned n_levels) +{ + TransferQueue &tq = device.get_transfer_queue(); + for(unsigned i=0; i+1(this)->storage_fmt)); + region.srcSubresource.mipLevel = i; + region.srcSubresource.baseArrayLayer = 0; + region.srcSubresource.layerCount = 1; + region.dstSubresource = region.srcSubresource; + ++region.dstSubresource.mipLevel; + + fill_mipmap_blit(i, ®ion); + + vk.CmdBlitImage(cmd_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ®ion, VK_FILTER_LINEAR); + }); + } +} + +void VulkanTexture::change_layout(unsigned n_levels, int level, unsigned layout, bool discard) const { - throw logic_error("VulkanTexture::generate_mipmap is unimplemented"); + unsigned aspect = get_vulkan_aspect(get_components(static_cast(this)->storage_fmt)); + if(n_levels>0) + device.get_synchronizer().split_image_mipmap(handle, aspect, n_levels); + device.get_synchronizer().change_image_layout(handle, aspect, level, layout, discard); } void VulkanTexture::set_debug_name(const string &name) @@ -84,9 +153,14 @@ void VulkanTexture::set_vulkan_object_names() const #ifdef DEBUG const VulkanFunctions &vk = device.get_functions(); - string view_name = debug_name+"/view"; VkDebugUtilsObjectNameInfoEXT name_info = { }; name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.objectType = VK_OBJECT_TYPE_IMAGE; + name_info.objectHandle = reinterpret_cast(handle); + name_info.pObjectName = debug_name.c_str(); + vk.SetDebugUtilsObjectName(name_info); + + string view_name = debug_name+"/view"; name_info.objectType = VK_OBJECT_TYPE_IMAGE_VIEW; name_info.objectHandle = reinterpret_cast(view_handle); name_info.pObjectName = view_name.c_str();