Source code for simvx.graphics.renderer.render_target

"""Offscreen render target with colour + depth attachments."""


from __future__ import annotations

import logging
from typing import Any

import vulkan as vk

from ..gpu.memory import create_image
from .passes import create_offscreen_pass

log = logging.getLogger(__name__)

__all__ = ["RenderTarget"]


[docs] class RenderTarget: """Manages an offscreen render target for render-to-texture.""" def __init__( self, device: Any, physical_device: Any, width: int, height: int, color_format: int = vk.VK_FORMAT_R8G8B8A8_UNORM, use_depth: bool = True, samplable_depth: bool = False, ) -> None: self.device = device self.width = width self.height = height self.color_format = color_format # Colour attachment (samplable) self.color_image, self.color_memory = create_image( device, physical_device, width, height, color_format, vk.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk.VK_IMAGE_USAGE_SAMPLED_BIT | vk.VK_IMAGE_USAGE_STORAGE_BIT, ) self.color_view = vk.vkCreateImageView(device, vk.VkImageViewCreateInfo( image=self.color_image, viewType=vk.VK_IMAGE_VIEW_TYPE_2D, format=color_format, subresourceRange=vk.VkImageSubresourceRange( aspectMask=vk.VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel=0, levelCount=1, baseArrayLayer=0, layerCount=1, ), ), None) # Depth attachment depth_fmt = vk.VK_FORMAT_D32_SFLOAT if use_depth else 0 if use_depth: self.depth_image, self.depth_memory = create_image( device, physical_device, width, height, depth_fmt, vk.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk.VK_IMAGE_USAGE_SAMPLED_BIT, ) self.depth_view = vk.vkCreateImageView(device, vk.VkImageViewCreateInfo( image=self.depth_image, viewType=vk.VK_IMAGE_VIEW_TYPE_2D, format=depth_fmt, subresourceRange=vk.VkImageSubresourceRange( aspectMask=vk.VK_IMAGE_ASPECT_DEPTH_BIT, baseMipLevel=0, levelCount=1, baseArrayLayer=0, layerCount=1, ), ), None) else: self.depth_image = self.depth_memory = self.depth_view = None # Render pass and framebuffer self.render_pass = create_offscreen_pass( device, color_format, depth_fmt, samplable_depth=samplable_depth, ) attachments = [self.color_view] if self.depth_view: attachments.append(self.depth_view) self.framebuffer = vk.vkCreateFramebuffer(device, vk.VkFramebufferCreateInfo( renderPass=self.render_pass, attachmentCount=len(attachments), pAttachments=attachments, width=width, height=height, layers=1, ), None)
[docs] def destroy(self) -> None: """Clean up all resources.""" vk.vkDestroyFramebuffer(self.device, self.framebuffer, None) vk.vkDestroyRenderPass(self.device, self.render_pass, None) if self.depth_view: vk.vkDestroyImageView(self.device, self.depth_view, None) if self.depth_image: vk.vkDestroyImage(self.device, self.depth_image, None) if self.depth_memory: vk.vkFreeMemory(self.device, self.depth_memory, None) vk.vkDestroyImageView(self.device, self.color_view, None) vk.vkDestroyImage(self.device, self.color_image, None) vk.vkFreeMemory(self.device, self.color_memory, None)