Path: blob/master/servers/rendering/renderer_rd/pipeline_deferred_rd.h
21345 views
/**************************************************************************/1/* pipeline_deferred_rd.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "servers/rendering/rendering_device.h"3334// Helper class for automatically deferring compilation of a pipeline to a background task.35// When attempting to retrieve the pipeline with the getter, the caller will automatically36// wait for it to be ready.3738class PipelineDeferredRD {39protected:40struct CreationParameters {41RID shader;42RD::FramebufferFormatID framebuffer_format;43RD::VertexFormatID vertex_format;44RD::RenderPrimitive render_primitive;45RD::PipelineRasterizationState rasterization_state;46RD::PipelineMultisampleState multisample_state;47RD::PipelineDepthStencilState depth_stencil_state;48RD::PipelineColorBlendState blend_state;49BitField<RD::PipelineDynamicStateFlags> dynamic_state_flags;50uint32_t for_render_pass;51Vector<RD::PipelineSpecializationConstant> specialization_constants;52bool is_compute;53};5455RID pipeline;56WorkerThreadPool::TaskID task = WorkerThreadPool::INVALID_TASK_ID;5758void _create(const CreationParameters &c) {59if (c.is_compute) {60pipeline = RD::get_singleton()->compute_pipeline_create(c.shader, c.specialization_constants);61} else {62pipeline = RD::get_singleton()->render_pipeline_create(c.shader, c.framebuffer_format, c.vertex_format, c.render_primitive, c.rasterization_state, c.multisample_state, c.depth_stencil_state, c.blend_state, c.dynamic_state_flags, c.for_render_pass, c.specialization_constants);63}64}6566void _start(const CreationParameters &c) {67free();68task = WorkerThreadPool::get_singleton()->add_template_task(this, &PipelineDeferredRD::_create, c, true, "PipelineCompilation");69}7071void _wait() {72if (task != WorkerThreadPool::INVALID_TASK_ID) {73WorkerThreadPool::get_singleton()->wait_for_task_completion(task);74task = WorkerThreadPool::INVALID_TASK_ID;75}76}7778public:79PipelineDeferredRD() {80// Default constructor.81}8283~PipelineDeferredRD() {84#ifdef DEV_ENABLED85ERR_FAIL_COND_MSG(pipeline.is_valid(), "'free()' must be called manually before deconstruction and before the corresponding shader is freed.");86#endif87}8889void create_render_pipeline(RID p_shader, RD::FramebufferFormatID p_framebuffer_format, RD::VertexFormatID p_vertex_format, RD::RenderPrimitive p_render_primitive, const RD::PipelineRasterizationState &p_rasterization_state, const RD::PipelineMultisampleState &p_multisample_state, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, BitField<RD::PipelineDynamicStateFlags> p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<RD::PipelineSpecializationConstant> &p_specialization_constants = Vector<RD::PipelineSpecializationConstant>()) {90CreationParameters c;91c.shader = p_shader;92c.framebuffer_format = p_framebuffer_format;93c.vertex_format = p_vertex_format;94c.render_primitive = p_render_primitive;95c.rasterization_state = p_rasterization_state;96c.multisample_state = p_multisample_state;97c.depth_stencil_state = p_depth_stencil_state;98c.blend_state = p_blend_state;99c.dynamic_state_flags = p_dynamic_state_flags;100c.for_render_pass = p_for_render_pass;101c.specialization_constants = p_specialization_constants;102c.is_compute = false;103_start(c);104}105106void create_compute_pipeline(RID p_shader, const Vector<RD::PipelineSpecializationConstant> &p_specialization_constants = Vector<RD::PipelineSpecializationConstant>()) {107CreationParameters c = {};108c.shader = p_shader;109c.specialization_constants = p_specialization_constants;110c.is_compute = true;111_start(c);112}113114RID get_rid() {115_wait();116return pipeline;117}118119void free() {120_wait();121122if (pipeline.is_valid()) {123#ifdef DEV_ENABLED124ERR_FAIL_COND_MSG(!(RD::get_singleton()->render_pipeline_is_valid(pipeline) || RD::get_singleton()->compute_pipeline_is_valid(pipeline)), "`free()` must be called manually before the dependent shader is freed.");125#endif126RD::get_singleton()->free_rid(pipeline);127pipeline = RID();128}129}130};131132133