]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/framebuffer_backend.cpp
Initial implementation of Vulkan backend
[libs/gl.git] / source / backends / vulkan / framebuffer_backend.cpp
diff --git a/source/backends/vulkan/framebuffer_backend.cpp b/source/backends/vulkan/framebuffer_backend.cpp
new file mode 100644 (file)
index 0000000..5b83c3d
--- /dev/null
@@ -0,0 +1,111 @@
+#include <msp/strings/format.h>
+#include "device.h"
+#include "framebuffer.h"
+#include "framebuffer_backend.h"
+#include "vulkan.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+VulkanFramebuffer::VulkanFramebuffer(bool):
+       device(Device::get_current())
+{ }
+
+VulkanFramebuffer::VulkanFramebuffer(VulkanFramebuffer &&other):
+       device(other.device),
+       handle(other.handle),
+       debug_name(move(other.debug_name))
+{
+       other.handle = 0;
+}
+
+VulkanFramebuffer::~VulkanFramebuffer()
+{
+       if(handle)
+               device.get_destroy_queue().destroy(handle);
+}
+
+bool VulkanFramebuffer::is_format_supported(const FrameFormat &fmt)
+{
+       const VulkanFunctions &vk = device.get_functions();
+       for(FrameAttachment a: fmt)
+       {
+               PixelFormat pf = get_attachment_pixelformat(a);
+               PixelComponents comp = get_components(pf);
+               VkFormatProperties props;
+               vk.GetPhysicalDeviceFormatProperties(static_cast<VkFormat>(get_vulkan_pixelformat(pf)), props);
+               if(comp==DEPTH_COMPONENT || comp==STENCIL_INDEX)
+               {
+                       if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
+                               return false;
+               }
+               else if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
+                       return false;
+       }
+
+       return true;
+}
+
+void VulkanFramebuffer::update(unsigned) const
+{
+       const Framebuffer &self = *static_cast<const Framebuffer *>(this);
+       const VulkanFunctions &vk = device.get_functions();
+
+       if(handle)
+               device.get_destroy_queue().destroy(handle);
+
+       VkImageView vk_attachments[FrameFormat::MAX_ATTACHMENTS] = { };
+       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;
+       }
+
+       VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(self.format, false, false);
+
+       VkFramebufferCreateInfo framebuffer_info = { };
+       framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+       framebuffer_info.renderPass = handle_cast<::VkRenderPass>(render_pass);
+       framebuffer_info.attachmentCount = self.format.size();
+       framebuffer_info.pAttachments = handle_cast<::VkImageView *>(vk_attachments);
+       framebuffer_info.width = self.width;
+       framebuffer_info.height = self.height;
+       framebuffer_info.layers = 1;
+
+       vk.CreateFramebuffer(framebuffer_info, handle);
+
+       if(!debug_name.empty())
+               set_vulkan_object_name();
+}
+
+void VulkanFramebuffer::set_debug_name(const string &name)
+{
+#ifdef DEBUG
+       debug_name = name;
+       if(handle)
+               set_vulkan_object_name();
+#else
+       (void)name;
+#endif
+}
+
+void VulkanFramebuffer::set_vulkan_object_name() const
+{
+#ifdef DEBUG
+       const VulkanFunctions &vk = device.get_functions();
+
+       VkDebugUtilsObjectNameInfoEXT name_info = { };
+       name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+       name_info.objectType = VK_OBJECT_TYPE_FRAMEBUFFER;
+       name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
+       name_info.pObjectName = debug_name.c_str();
+       vk.SetDebugUtilsObjectName(name_info);
+#endif
+}
+
+} // namespace GL
+} // namespace Msp