]> git.tdb.fi Git - libs/gl.git/commitdiff
Create image views in VulkanFramebuffer if necessary
authorMikko Rasa <tdb@tdb.fi>
Fri, 10 Dec 2021 13:53:46 +0000 (15:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 10 Dec 2021 23:32:45 +0000 (01:32 +0200)
Using a specific mip level or array layer as an attachment requires a
view with suitable parameters.

source/backends/vulkan/framebuffer_backend.cpp
source/backends/vulkan/framebuffer_backend.h

index 61ab1caeef75504063f4f3a34475056ac292b142..16894a58369f8639bfcc15260505d50a7ab8b8cf 100644 (file)
@@ -23,8 +23,12 @@ VulkanFramebuffer::VulkanFramebuffer(VulkanFramebuffer &&other):
 
 VulkanFramebuffer::~VulkanFramebuffer()
 {
+       DestroyQueue &dq = device.get_destroy_queue();
        if(handle)
-               device.get_destroy_queue().destroy(handle);
+               dq.destroy(handle);
+       for(VkImageView h: view_handles)
+               if(h)
+                       dq.destroy(h);
 }
 
 bool VulkanFramebuffer::is_format_supported(const FrameFormat &fmt)
@@ -48,11 +52,14 @@ bool VulkanFramebuffer::is_format_supported(const FrameFormat &fmt)
        return true;
 }
 
-void VulkanFramebuffer::update(unsigned) const
+void VulkanFramebuffer::update(unsigned mask) const
 {
        const Framebuffer &self = *static_cast<const Framebuffer *>(this);
        const VulkanFunctions &vk = device.get_functions();
 
+       if(self.attachments.size()>view_handles.size())
+               view_handles.resize(self.attachments.size());
+
        if(handle)
                device.get_destroy_queue().destroy(handle);
 
@@ -60,9 +67,48 @@ void VulkanFramebuffer::update(unsigned) const
        unsigned i = 0;
        for(const Framebuffer::Attachment &a: self.attachments)
        {
-               if(a.tex->view_type!=VK_IMAGE_VIEW_TYPE_2D || a.level || a.layer)
-                       throw logic_error("Unimplemented texture type in VulkanFramebuffer::update");
-               vk_attachments[i++] = a.tex->view_handle;
+               bool use_tex_view = (a.tex->view_type==VK_IMAGE_VIEW_TYPE_2D || (a.tex->view_type==VK_IMAGE_VIEW_TYPE_2D_ARRAY && a.layer<0));
+
+               if(mask&(1<<i))
+               {
+                       if(use_tex_view)
+                               a.tex->refresh_mip_views();
+                       else
+                       {
+                               if(view_handles[i])
+                                       device.get_destroy_queue().destroy(view_handles[i]);
+
+                               PixelFormat tex_format = a.tex->get_format();
+
+                               VkImageViewCreateInfo view_info = { };
+                               view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+                               view_info.image = handle_cast<::VkImage>(a.tex->handle);
+                               view_info.viewType = (a.layer<0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
+                               view_info.format = static_cast<VkFormat>(get_vulkan_pixelformat(tex_format));
+
+                               view_info.components.r = VK_COMPONENT_SWIZZLE_R;
+                               view_info.components.g = VK_COMPONENT_SWIZZLE_G;
+                               view_info.components.b = VK_COMPONENT_SWIZZLE_B;
+                               view_info.components.a = VK_COMPONENT_SWIZZLE_A;
+
+                               view_info.subresourceRange.aspectMask = get_vulkan_aspect(get_components(tex_format));
+                               view_info.subresourceRange.baseMipLevel = a.level;
+                               view_info.subresourceRange.levelCount = 1;
+                               view_info.subresourceRange.baseArrayLayer = max(a.layer, 0);
+                               view_info.subresourceRange.layerCount = (a.layer<0 ? VK_REMAINING_ARRAY_LAYERS : 1);
+
+                               vk.CreateImageView(view_info, view_handles[i]);
+                       }
+               }
+
+               if(use_tex_view)
+                       vk_attachments[i] = a.tex->mip_view_handles[a.level];
+               else if(view_handles[i])
+                       vk_attachments[i] = view_handles[i];
+               else
+                       throw logic_error("unexpected framebuffer configuration");
+
+               ++i;
        }
 
        VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(self.format, false, false, false);
index b990d307db6dbf4c119917553a3c56073f208c11..b53d1751928a4098b1e3580776d74f15850c98e5 100644 (file)
@@ -19,6 +19,7 @@ class VulkanFramebuffer: public NonCopyable
 protected:
        Device &device;
        mutable VkFramebuffer handle = 0;
+       mutable std::vector<VkImageView> view_handles;
        std::string debug_name;
 
        VulkanFramebuffer(bool);