3 #include "synchronizer.h"
5 #include "texture_backend.h"
13 VulkanTexture::VulkanTexture(unsigned t):
14 device(Device::get_current()),
18 VulkanTexture::VulkanTexture(VulkanTexture &&other):
21 view_handle(other.view_handle),
22 memory_id(other.memory_id),
23 view_type(other.view_type),
24 debug_name(move(other.debug_name))
27 other.view_handle = 0;
31 VulkanTexture::~VulkanTexture()
33 DestroyQueue &dq = device.get_destroy_queue();
36 dq.destroy(view_handle);
38 dq.destroy(handle, memory_id);
41 void VulkanTexture::allocate()
43 const Texture &self = *static_cast<const Texture *>(this);
44 const VulkanFunctions &vk = device.get_functions();
46 VkImageCreateInfo image_info = { };
47 image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
48 image_info.format = static_cast<VkFormat>(get_vulkan_pixelformat(self.storage_fmt));
49 image_info.extent.width = 1;
50 image_info.extent.height = 1;
51 image_info.extent.depth = 1;
52 image_info.mipLevels = self.n_levels;
53 image_info.arrayLayers = 1;
54 image_info.samples = VK_SAMPLE_COUNT_1_BIT;
55 image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
56 image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
57 image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
59 image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
60 PixelComponents comp = get_components(self.storage_fmt);
61 if(comp==DEPTH_COMPONENT || comp==STENCIL_INDEX)
62 image_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
64 image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
66 fill_image_info(&image_info);
68 /* SwapChainTexture may have already provided the image. Create_info is
69 filled anyway because some of its fields are used for view_info. */
72 vk.CreateImage(image_info, handle);
73 memory_id = device.get_allocator().allocate(handle, DEVICE_MEMORY);
75 // Trigger a layout transition if the image is used before uploading data.
76 change_layout(-1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
79 VkImageViewCreateInfo view_info = { };
80 view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
81 view_info.image = handle_cast<::VkImage>(handle);
82 view_info.viewType = static_cast<VkImageViewType>(view_type);
83 view_info.format = image_info.format;
85 const unsigned *swizzle_order = get_vulkan_swizzle(self.swizzle);
86 view_info.components.r = static_cast<VkComponentSwizzle>(swizzle_order[0]);
87 view_info.components.g = static_cast<VkComponentSwizzle>(swizzle_order[1]);
88 view_info.components.b = static_cast<VkComponentSwizzle>(swizzle_order[2]);
89 view_info.components.a = static_cast<VkComponentSwizzle>(swizzle_order[3]);
91 view_info.subresourceRange.aspectMask = get_vulkan_aspect(get_components(self.storage_fmt));
92 view_info.subresourceRange.baseMipLevel = 0;
93 view_info.subresourceRange.levelCount = image_info.mipLevels;
94 view_info.subresourceRange.baseArrayLayer = 0;
95 view_info.subresourceRange.layerCount = image_info.arrayLayers;
97 vk.CreateImageView(view_info, view_handle);
99 if(!debug_name.empty())
100 set_vulkan_object_names();
103 void VulkanTexture::stage_pixels(void *staging, const void *data, size_t count)
105 const Texture &self = *static_cast<const Texture *>(this);
107 if(self.swizzle==RGBA_TO_RGB)
109 const uint32_t *src = static_cast<const uint32_t *>(data);
110 uint32_t *dst = static_cast<uint32_t *>(staging);
112 for(; i+3<count; i+=4)
114 dst[0] = src[0]|0xFF000000;
115 dst[1] = (src[0]>>24)|(src[1]<<8)|0xFF000000;
116 dst[2] = (src[1]>>16)|(src[2]<<16)|0xFF000000;
117 dst[3] = (src[2]>>8)|0xFF000000;
124 const uint8_t *src_bytes = reinterpret_cast<const uint8_t *>(src);
127 *dst++ = src_bytes[0]|(src_bytes[1]<<8)|(src_bytes[2]<<16)|0xFF000000;
134 const char *src = static_cast<const char *>(data);
135 size_t data_size = count*get_pixel_size(self.storage_fmt);
136 copy(src, src+data_size, static_cast<char *>(staging));
140 void VulkanTexture::generate_mipmap()
142 unsigned n_levels = static_cast<const Texture *>(this)->n_levels;
144 TransferQueue &tq = device.get_transfer_queue();
145 for(unsigned i=0; i+1<n_levels; ++i)
147 tq.prepare_transfer(this, true, 0,
149 change_layout(i, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
150 change_layout(i+1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
152 [this, i](VkCommandBuffer cmd_buf, VkBuffer, size_t){
153 const VulkanFunctions &vk = device.get_functions();
155 VkImageBlit region = { };
156 region.srcSubresource.aspectMask = get_vulkan_aspect(get_components(static_cast<const Texture *>(this)->storage_fmt));
157 region.srcSubresource.mipLevel = i;
158 region.srcSubresource.baseArrayLayer = 0;
159 region.srcSubresource.layerCount = 1;
160 region.dstSubresource = region.srcSubresource;
161 ++region.dstSubresource.mipLevel;
163 fill_mipmap_blit(i, ®ion);
165 vk.CmdBlitImage(cmd_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
166 1, ®ion, VK_FILTER_LINEAR);
171 void VulkanTexture::change_layout(int level, unsigned layout, bool discard) const
173 const Texture &self = *static_cast<const Texture *>(this);
175 unsigned aspect = get_vulkan_aspect(get_components(self.storage_fmt));
177 device.get_synchronizer().split_image_mipmap(handle, aspect, self.n_levels);
178 device.get_synchronizer().change_image_layout(handle, aspect, level, layout, discard);
181 void VulkanTexture::set_debug_name(const string &name)
186 set_vulkan_object_names();
192 void VulkanTexture::set_vulkan_object_names() const
195 const VulkanFunctions &vk = device.get_functions();
197 VkDebugUtilsObjectNameInfoEXT name_info = { };
198 name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
199 name_info.objectType = VK_OBJECT_TYPE_IMAGE;
200 name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
201 name_info.pObjectName = debug_name.c_str();
202 vk.SetDebugUtilsObjectName(name_info);
204 string view_name = debug_name+"/view";
205 name_info.objectType = VK_OBJECT_TYPE_IMAGE_VIEW;
206 name_info.objectHandle = reinterpret_cast<uint64_t>(view_handle);
207 name_info.pObjectName = view_name.c_str();
208 vk.SetDebugUtilsObjectName(name_info);