Source code for simvx.graphics.renderer.pipeline_manager

"""PipelineManager — owns the forward renderer's 3D graphics pipelines.

Extracted from Renderer so pipeline creation, rebuild-on-HDR-switch,
resize, and cleanup live in one place. Renderer re-exports the
pipeline handles as attributes so SceneContentRenderer keeps accessing
``renderer._pipeline`` etc. without change.
"""

from typing import Any

import vulkan as vk

from ..gpu.pipeline import (
    create_forward_pipeline,
    create_shader_module,
    create_skinned_pipeline,
    create_transparent_pipeline,
)
from ..materials.shader_compiler import compile_shader

__all__ = ["PipelineManager"]

[docs] class PipelineManager: """Owns the 3D forward-render pipelines and their shader modules.""" def __init__(self, engine: Any) -> None: self._engine = engine self.vert_module: Any = None self.frag_module: Any = None self.skinned_vert_module: Any = None self.opaque: Any = None self.opaque_layout: Any = None self.nocull: Any = None self.nocull_layout: Any = None self.transparent: Any = None self.transparent_layout: Any = None self.skinned: Any = None self.skinned_layout: Any = None self._ssbo_layout: Any = None self._joint_layout: Any = None
[docs] def setup(self, ssbo_layout: Any, joint_layout: Any) -> None: """Compile shaders and build the four 3D pipelines against the engine render pass.""" self._ssbo_layout = ssbo_layout self._joint_layout = joint_layout e = self._engine device = e.ctx.device shader_dir = e.shader_dir vert_spv = compile_shader(shader_dir / "cube.vert") frag_spv = compile_shader(shader_dir / "cube_textured.frag") self.vert_module = create_shader_module(device, vert_spv) self.frag_module = create_shader_module(device, frag_spv) skinned_vert_spv = compile_shader(shader_dir / "skinned.vert") self.skinned_vert_module = create_shader_module(device, skinned_vert_spv) self._build_pipelines(e.render_pass, e.extent)
[docs] def rebuild_for_render_pass(self, render_pass: Any) -> None: """Rebuild all four pipelines against ``render_pass`` (e.g. HDR target).""" self._destroy_pipelines() self._build_pipelines(render_pass, self._engine.extent)
[docs] def rebuild_for_resize(self, width: int, height: int, render_pass: Any) -> None: """Rebuild all four pipelines for a new framebuffer size.""" self._destroy_pipelines() self._build_pipelines(render_pass, (width, height))
[docs] def cleanup(self) -> None: """Destroy pipelines, layouts, and shader modules.""" self._destroy_pipelines() device = self._engine.ctx.device for mod in (self.skinned_vert_module, self.vert_module, self.frag_module): if mod: vk.vkDestroyShaderModule(device, mod, None) self.skinned_vert_module = self.vert_module = self.frag_module = None
def _build_pipelines(self, render_pass: Any, extent: Any) -> None: e = self._engine device = e.ctx.device tex_layout = e.texture_descriptor_layout self.opaque, self.opaque_layout = create_forward_pipeline( device, self.vert_module, self.frag_module, render_pass, extent, self._ssbo_layout, texture_layout=tex_layout, ) self.nocull, self.nocull_layout = create_forward_pipeline( device, self.vert_module, self.frag_module, render_pass, extent, self._ssbo_layout, texture_layout=tex_layout, double_sided=True, ) self.transparent, self.transparent_layout = create_transparent_pipeline( device, self.vert_module, self.frag_module, render_pass, extent, self._ssbo_layout, texture_layout=tex_layout, ) self.skinned, self.skinned_layout = create_skinned_pipeline( device, self.skinned_vert_module, self.frag_module, render_pass, extent, self._ssbo_layout, texture_layout=tex_layout, joint_layout=self._joint_layout, ) def _destroy_pipelines(self) -> None: device = self._engine.ctx.device for pipeline, layout in ( (self.opaque, self.opaque_layout), (self.nocull, self.nocull_layout), (self.transparent, self.transparent_layout), (self.skinned, self.skinned_layout), ): if pipeline: vk.vkDestroyPipeline(device, pipeline, None) if layout: vk.vkDestroyPipelineLayout(device, layout, None) self.opaque = self.opaque_layout = None self.nocull = self.nocull_layout = None self.transparent = self.transparent_layout = None self.skinned = self.skinned_layout = None