/* Copyright (c) 2019-2025, Arm Limited and Contributors * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 the "License"; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "render_pipeline.h" #include "scene_graph/components/camera.h" #include "scene_graph/components/image.h" #include "scene_graph/components/material.h" #include "scene_graph/components/mesh.h" #include "scene_graph/components/pbr_material.h" #include "scene_graph/components/sampler.h" #include "scene_graph/components/sub_mesh.h" #include "scene_graph/components/texture.h" #include "scene_graph/node.h" namespace vkb { RenderPipeline::RenderPipeline(std::vector> &&subpasses_) : subpasses{std::move(subpasses_)} { prepare(); // Default load/store for swapchain load_store[0].load_op = VK_ATTACHMENT_LOAD_OP_CLEAR; load_store[0].store_op = VK_ATTACHMENT_STORE_OP_STORE; // Default load/store for depth attachment load_store[1].load_op = VK_ATTACHMENT_LOAD_OP_CLEAR; load_store[1].store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Default clear value clear_value[0].color = {0.0f, 0.0f, 0.0f, 1.0f}; clear_value[1].depthStencil = {0.0f, ~0U}; } void RenderPipeline::prepare() { for (auto &subpass : subpasses) { subpass->prepare(); } } void RenderPipeline::add_subpass(std::unique_ptr &&subpass) { subpass->prepare(); subpasses.emplace_back(std::move(subpass)); } std::vector> &RenderPipeline::get_subpasses() { return subpasses; } const std::vector &RenderPipeline::get_load_store() const { return load_store; } void RenderPipeline::set_load_store(const std::vector &ls) { load_store = ls; } const std::vector &RenderPipeline::get_clear_value() const { return clear_value; } void RenderPipeline::set_clear_value(const std::vector &cv) { clear_value = cv; } void RenderPipeline::draw(vkb::core::CommandBufferC &command_buffer, RenderTarget &render_target, VkSubpassContents contents) { assert(!subpasses.empty() && "Render pipeline should contain at least one sub-pass"); // Pad clear values if they're less than render target attachments while (clear_value.size() < render_target.get_attachments().size()) { clear_value.push_back({0.0f, 0.0f, 0.0f, 1.0f}); } for (size_t i = 0; i < subpasses.size(); ++i) { active_subpass_index = i; auto &subpass = subpasses[i]; subpass->update_render_target_attachments(render_target); if (i == 0) { command_buffer.begin_render_pass(render_target, load_store, clear_value, subpasses, contents); } else { command_buffer.next_subpass(); } if (subpass->get_debug_name().empty()) { subpass->set_debug_name(fmt::format("RP subpass #{}", i)); } ScopedDebugLabel subpass_debug_label{command_buffer, subpass->get_debug_name().c_str()}; subpass->draw(command_buffer); } active_subpass_index = 0; } std::unique_ptr &RenderPipeline::get_active_subpass() { return subpasses[active_subpass_index]; } } // namespace vkb