]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/texture_backend.cpp
Store the number of mipmap levels in the Texture base class
[libs/gl.git] / source / backends / vulkan / texture_backend.cpp
index 168d6adb0501d69a501b83e8bb726a860fd8e978..ec6d504732f9f0a13055eff1f42086d2fe4858a7 100644 (file)
@@ -49,7 +49,7 @@ void VulkanTexture::allocate()
        image_info.extent.width = 1;
        image_info.extent.height = 1;
        image_info.extent.depth = 1;
-       image_info.mipLevels = 1;
+       image_info.mipLevels = self.n_levels;
        image_info.arrayLayers = 1;
        image_info.samples = VK_SAMPLE_COUNT_1_BIT;
        image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
@@ -73,7 +73,7 @@ void VulkanTexture::allocate()
                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);
+               change_layout(-1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
        }
 
        VkImageViewCreateInfo view_info = { };
@@ -100,15 +100,54 @@ void VulkanTexture::allocate()
                set_vulkan_object_names();
 }
 
-void VulkanTexture::generate_mipmap_levels(unsigned n_levels)
+void VulkanTexture::stage_pixels(void *staging, const void *data, size_t count)
 {
+       const Texture &self = *static_cast<const Texture *>(this);
+
+       if(self.swizzle==RGBA_TO_RGB)
+       {
+               const uint32_t *src = static_cast<const uint32_t *>(data);
+               uint32_t *dst = static_cast<uint32_t *>(staging);
+               size_t i = 0;
+               for(; i+3<count; i+=4)
+               {
+                       dst[0] = src[0]|0xFF000000;
+                       dst[1] = (src[0]>>24)|(src[1]<<8)|0xFF000000;
+                       dst[2] = (src[1]>>16)|(src[2]<<16)|0xFF000000;
+                       dst[3] = (src[2]>>8)|0xFF000000;
+                       src += 3;
+                       dst += 4;
+               }
+
+               if(i<count)
+               {
+                       const uint8_t *src_bytes = reinterpret_cast<const uint8_t *>(src);
+                       for(; i<count; ++i)
+                       {
+                               *dst++ = src_bytes[0]|(src_bytes[1]<<8)|(src_bytes[2]<<16)|0xFF000000;
+                               src_bytes += 3;
+                       }
+               }
+       }
+       else
+       {
+               const char *src = static_cast<const char *>(data);
+               size_t data_size = count*get_pixel_size(self.storage_fmt);
+               copy(src, src+data_size, static_cast<char *>(staging));
+       }
+}
+
+void VulkanTexture::generate_mipmap()
+{
+       unsigned n_levels = static_cast<const Texture *>(this)->n_levels;
+
        TransferQueue &tq = device.get_transfer_queue();
        for(unsigned i=0; i+1<n_levels; ++i)
        {
                tq.prepare_transfer(this, true, 0,
-                       [this, n_levels, i](){
-                               change_layout((i==0 ? n_levels : 0), i, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
-                               change_layout(0, i+1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
+                       [this, i](){
+                               change_layout(i, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
+                               change_layout(i+1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
                        },
                        [this, i](VkCommandBuffer cmd_buf, VkBuffer, size_t){
                                const VulkanFunctions &vk = device.get_functions();
@@ -129,11 +168,13 @@ void VulkanTexture::generate_mipmap_levels(unsigned n_levels)
        }
 }
 
-void VulkanTexture::change_layout(unsigned n_levels, int level, unsigned layout, bool discard) const
+void VulkanTexture::change_layout(int level, unsigned layout, bool discard) const
 {
-       unsigned aspect = get_vulkan_aspect(get_components(static_cast<const Texture *>(this)->storage_fmt));
-       if(n_levels>0)
-               device.get_synchronizer().split_image_mipmap(handle, aspect, n_levels);
+       const Texture &self = *static_cast<const Texture *>(this);
+
+       unsigned aspect = get_vulkan_aspect(get_components(self.storage_fmt));
+       if(level>=0)
+               device.get_synchronizer().split_image_mipmap(handle, aspect, self.n_levels);
        device.get_synchronizer().change_image_layout(handle, aspect, level, layout, discard);
 }