Files
XCEngine/engine/src/Rendering/Internal/RenderPipelineFactory.cpp

578 lines
18 KiB
C++
Raw Normal View History

#include "Rendering/Internal/RenderPipelineFactory.h"
#include <XCEngine/Rendering/RenderPipelineAsset.h>
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
#include "Rendering/Passes/BuiltinObjectIdPass.h"
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
#include <mutex>
#include <unordered_map>
#include <unordered_set>
namespace XCEngine {
namespace Rendering {
namespace Internal {
namespace {
std::shared_ptr<const RenderPipelineAsset>
CreateBuiltinForwardPipelineRendererAsset() {
static const std::shared_ptr<const RenderPipelineAsset>
s_builtinForwardPipelineAsset =
std::make_shared<Pipelines::BuiltinForwardPipelineAsset>();
return s_builtinForwardPipelineAsset;
}
std::unique_ptr<RenderPass> CreateBuiltinDepthOnlyStandalonePass() {
return std::make_unique<Passes::BuiltinDepthOnlyPass>();
}
std::unique_ptr<RenderPass> CreateBuiltinObjectIdStandalonePass() {
return std::make_unique<Passes::BuiltinObjectIdPass>();
}
std::unique_ptr<RenderPass> CreateBuiltinShadowCasterStandalonePass() {
return std::make_unique<Passes::BuiltinShadowCasterPass>();
}
using PipelineRendererAssetRegistry =
std::unordered_map<std::string, PipelineRendererAssetFactory>;
using CameraFrameStandalonePassRegistry =
std::unordered_map<std::string, CameraFrameStandalonePassFactory>;
using DirectionalShadowPlanningPolicyRegistry =
std::unordered_map<std::string, DirectionalShadowPlanningPolicy>;
using DirectionalShadowExecutionPolicyRegistry =
std::unordered_map<std::string, DirectionalShadowExecutionPolicy>;
PipelineRendererAssetRegistry& GetPipelineRendererAssetRegistry() {
static PipelineRendererAssetRegistry registry = {};
return registry;
}
CameraFrameStandalonePassRegistry& GetCameraFrameStandalonePassRegistry() {
static CameraFrameStandalonePassRegistry registry = {};
return registry;
}
DirectionalShadowPlanningPolicyRegistry&
GetDirectionalShadowPlanningPolicyRegistry() {
static DirectionalShadowPlanningPolicyRegistry registry = {};
return registry;
}
DirectionalShadowExecutionPolicyRegistry&
GetDirectionalShadowExecutionPolicyRegistry() {
static DirectionalShadowExecutionPolicyRegistry registry = {};
return registry;
}
std::unordered_set<std::string>& GetBuiltinPipelineRendererAssetKeys() {
static std::unordered_set<std::string> builtinKeys = {};
return builtinKeys;
}
std::unordered_set<std::string>& GetBuiltinCameraFrameStandalonePassKeys() {
static std::unordered_set<std::string> builtinKeys = {};
return builtinKeys;
}
std::unordered_set<std::string>& GetBuiltinDirectionalShadowPlanningPolicyKeys() {
static std::unordered_set<std::string> builtinKeys = {};
return builtinKeys;
}
std::unordered_set<std::string>&
GetBuiltinDirectionalShadowExecutionPolicyKeys() {
static std::unordered_set<std::string> builtinKeys = {};
return builtinKeys;
}
std::mutex& GetPipelineRendererAssetRegistryMutex() {
static std::mutex mutex;
return mutex;
}
std::mutex& GetCameraFrameStandalonePassRegistryMutex() {
static std::mutex mutex;
return mutex;
}
std::mutex& GetDirectionalShadowPlanningPolicyRegistryMutex() {
static std::mutex mutex;
return mutex;
}
std::mutex& GetDirectionalShadowExecutionPolicyRegistryMutex() {
static std::mutex mutex;
return mutex;
}
void EnsureBuiltinPipelineRendererAssetRegistryInitialized() {
static const bool initialized = []() {
PipelineRendererAssetRegistry& registry =
GetPipelineRendererAssetRegistry();
registry.emplace(
"BuiltinForward",
&CreateBuiltinForwardPipelineRendererAsset);
GetBuiltinPipelineRendererAssetKeys().insert("BuiltinForward");
return true;
}();
(void)initialized;
}
void EnsureBuiltinCameraFrameStandalonePassRegistryInitialized() {
static const bool initialized = []() {
CameraFrameStandalonePassRegistry& registry =
GetCameraFrameStandalonePassRegistry();
registry.emplace(
"BuiltinDepthOnly",
&CreateBuiltinDepthOnlyStandalonePass);
registry.emplace(
"BuiltinObjectId",
&CreateBuiltinObjectIdStandalonePass);
registry.emplace(
"BuiltinShadowCaster",
&CreateBuiltinShadowCasterStandalonePass);
std::unordered_set<std::string>& builtinKeys =
GetBuiltinCameraFrameStandalonePassKeys();
builtinKeys.insert("BuiltinDepthOnly");
builtinKeys.insert("BuiltinObjectId");
builtinKeys.insert("BuiltinShadowCaster");
return true;
}();
(void)initialized;
}
void EnsureBuiltinDirectionalShadowPlanningPolicyRegistryInitialized() {
static const bool initialized = []() {
DirectionalShadowPlanningPolicyRegistry& registry =
GetDirectionalShadowPlanningPolicyRegistry();
registry.emplace(
"BuiltinDirectionalShadowPlanning",
[](CameraRenderRequest& request,
size_t renderedBaseCameraCount,
size_t renderedRequestCount,
const DirectionalShadowPlanningSettings& settings) {
ApplyDefaultRenderPipelineAssetCameraRenderRequestPolicy(
request,
renderedBaseCameraCount,
renderedRequestCount,
settings);
});
GetBuiltinDirectionalShadowPlanningPolicyKeys().insert(
"BuiltinDirectionalShadowPlanning");
return true;
}();
(void)initialized;
}
void EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized() {
static const bool initialized = []() {
DirectionalShadowExecutionPolicyRegistry& registry =
GetDirectionalShadowExecutionPolicyRegistry();
registry.emplace(
"BuiltinDirectionalShadow",
[](const CameraFramePlan& plan,
const DirectionalShadowSurfaceAllocation& shadowAllocation,
DirectionalShadowExecutionState& shadowState) {
ApplyDefaultRenderPipelineDirectionalShadowExecutionPolicy(
plan,
shadowAllocation,
shadowState);
return shadowState.shadowCasterRequest.IsValid() &&
shadowState.shadowData.IsValid();
});
GetBuiltinDirectionalShadowExecutionPolicyKeys().insert(
"BuiltinDirectionalShadow");
return true;
}();
(void)initialized;
}
std::unique_ptr<NativeSceneRenderer> TryCreateNativeSceneRendererFromAsset(
const std::shared_ptr<const RenderPipelineAsset>& asset) {
if (asset == nullptr) {
return nullptr;
}
std::unique_ptr<RenderPipeline> pipeline = asset->CreatePipeline();
if (pipeline == nullptr) {
return nullptr;
}
NativeSceneRenderer* const sceneRenderer =
dynamic_cast<NativeSceneRenderer*>(pipeline.get());
if (sceneRenderer == nullptr) {
return nullptr;
}
(void)pipeline.release();
return std::unique_ptr<NativeSceneRenderer>(sceneRenderer);
}
} // namespace
std::shared_ptr<const RenderPipelineAsset> CreateConfiguredRenderPipelineAsset() {
return Pipelines::CreateConfiguredManagedRenderPipelineAsset();
}
std::shared_ptr<const RenderPipelineAsset> CreateFallbackRenderPipelineAsset() {
return std::make_shared<Pipelines::ScriptableRenderPipelineHostAsset>();
}
bool RegisterPipelineRendererAssetFactory(
const std::string& key,
PipelineRendererAssetFactory factory) {
if (key.empty() || !factory) {
return false;
}
EnsureBuiltinPipelineRendererAssetRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetPipelineRendererAssetRegistryMutex());
PipelineRendererAssetRegistry& registry =
GetPipelineRendererAssetRegistry();
if (registry.find(key) != registry.end()) {
return false;
}
registry.emplace(key, std::move(factory));
return true;
}
bool UnregisterPipelineRendererAssetFactory(const std::string& key) {
if (key.empty()) {
return false;
}
EnsureBuiltinPipelineRendererAssetRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetPipelineRendererAssetRegistryMutex());
if (GetBuiltinPipelineRendererAssetKeys().find(key) !=
GetBuiltinPipelineRendererAssetKeys().end()) {
return false;
}
PipelineRendererAssetRegistry& registry =
GetPipelineRendererAssetRegistry();
return registry.erase(key) != 0u;
}
std::shared_ptr<const RenderPipelineAsset> CreatePipelineRendererAssetByKey(
const std::string& key) {
if (key.empty()) {
return nullptr;
}
EnsureBuiltinPipelineRendererAssetRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetPipelineRendererAssetRegistryMutex());
const PipelineRendererAssetRegistry& registry =
GetPipelineRendererAssetRegistry();
const auto it = registry.find(key);
if (it == registry.end() || !it->second) {
return nullptr;
}
return it->second();
}
bool RegisterCameraFrameStandalonePassFactory(
const std::string& key,
CameraFrameStandalonePassFactory factory) {
if (key.empty() || !factory) {
return false;
}
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetCameraFrameStandalonePassRegistryMutex());
CameraFrameStandalonePassRegistry& registry =
GetCameraFrameStandalonePassRegistry();
if (registry.find(key) != registry.end()) {
return false;
}
registry.emplace(key, std::move(factory));
return true;
}
bool UnregisterCameraFrameStandalonePassFactory(
const std::string& key) {
if (key.empty()) {
return false;
}
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetCameraFrameStandalonePassRegistryMutex());
if (GetBuiltinCameraFrameStandalonePassKeys().find(key) !=
GetBuiltinCameraFrameStandalonePassKeys().end()) {
return false;
}
CameraFrameStandalonePassRegistry& registry =
GetCameraFrameStandalonePassRegistry();
return registry.erase(key) != 0u;
}
std::unique_ptr<RenderPass> CreateCameraFrameStandalonePassByKey(
const std::string& key) {
if (key.empty()) {
return nullptr;
}
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetCameraFrameStandalonePassRegistryMutex());
const CameraFrameStandalonePassRegistry& registry =
GetCameraFrameStandalonePassRegistry();
const auto it = registry.find(key);
if (it == registry.end() || !it->second) {
return nullptr;
}
return it->second();
}
bool RegisterDirectionalShadowPlanningPolicy(
const std::string& key,
DirectionalShadowPlanningPolicy policy) {
if (key.empty() || !policy) {
return false;
}
EnsureBuiltinDirectionalShadowPlanningPolicyRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetDirectionalShadowPlanningPolicyRegistryMutex());
DirectionalShadowPlanningPolicyRegistry& registry =
GetDirectionalShadowPlanningPolicyRegistry();
if (registry.find(key) != registry.end()) {
return false;
}
registry.emplace(key, std::move(policy));
return true;
}
bool UnregisterDirectionalShadowPlanningPolicy(
const std::string& key) {
if (key.empty()) {
return false;
}
EnsureBuiltinDirectionalShadowPlanningPolicyRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetDirectionalShadowPlanningPolicyRegistryMutex());
if (GetBuiltinDirectionalShadowPlanningPolicyKeys().find(key) !=
GetBuiltinDirectionalShadowPlanningPolicyKeys().end()) {
return false;
}
DirectionalShadowPlanningPolicyRegistry& registry =
GetDirectionalShadowPlanningPolicyRegistry();
return registry.erase(key) != 0u;
}
bool ApplyDirectionalShadowPlanningPolicyByKey(
const std::string& key,
CameraRenderRequest& request,
size_t renderedBaseCameraCount,
size_t renderedRequestCount,
const DirectionalShadowPlanningSettings& settings) {
if (key.empty()) {
return false;
}
EnsureBuiltinDirectionalShadowPlanningPolicyRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetDirectionalShadowPlanningPolicyRegistryMutex());
const DirectionalShadowPlanningPolicyRegistry& registry =
GetDirectionalShadowPlanningPolicyRegistry();
const auto it = registry.find(key);
if (it == registry.end() || !it->second) {
return false;
}
it->second(
request,
renderedBaseCameraCount,
renderedRequestCount,
settings);
return true;
}
bool RegisterDirectionalShadowExecutionPolicy(
const std::string& key,
DirectionalShadowExecutionPolicy policy) {
if (key.empty() || !policy) {
return false;
}
EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetDirectionalShadowExecutionPolicyRegistryMutex());
DirectionalShadowExecutionPolicyRegistry& registry =
GetDirectionalShadowExecutionPolicyRegistry();
if (registry.find(key) != registry.end()) {
return false;
}
registry.emplace(key, std::move(policy));
return true;
}
bool UnregisterDirectionalShadowExecutionPolicy(
const std::string& key) {
if (key.empty()) {
return false;
}
EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetDirectionalShadowExecutionPolicyRegistryMutex());
if (GetBuiltinDirectionalShadowExecutionPolicyKeys().find(key) !=
GetBuiltinDirectionalShadowExecutionPolicyKeys().end()) {
return false;
}
DirectionalShadowExecutionPolicyRegistry& registry =
GetDirectionalShadowExecutionPolicyRegistry();
return registry.erase(key) != 0u;
}
bool ConfigureDirectionalShadowExecutionStateByKey(
const std::string& key,
const CameraFramePlan& plan,
const DirectionalShadowSurfaceAllocation& shadowAllocation,
DirectionalShadowExecutionState& shadowState) {
if (key.empty()) {
return false;
}
EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized();
std::lock_guard<std::mutex> lock(
GetDirectionalShadowExecutionPolicyRegistryMutex());
const DirectionalShadowExecutionPolicyRegistry& registry =
GetDirectionalShadowExecutionPolicyRegistry();
const auto it = registry.find(key);
if (it == registry.end() || !it->second) {
return false;
}
return it->second(
plan,
shadowAllocation,
shadowState);
}
std::shared_ptr<const RenderPipelineAsset> ResolveRenderPipelineAssetOrDefault(
std::shared_ptr<const RenderPipelineAsset> preferredAsset) {
if (preferredAsset != nullptr) {
return std::move(preferredAsset);
}
if (std::shared_ptr<const RenderPipelineAsset> configuredAsset =
CreateConfiguredRenderPipelineAsset();
configuredAsset != nullptr) {
return configuredAsset;
}
return CreateFallbackRenderPipelineAsset();
}
std::unique_ptr<RenderPipeline> CreateRenderPipelineOrDefault(
const std::shared_ptr<const RenderPipelineAsset>& preferredAsset,
std::shared_ptr<const RenderPipelineAsset>* outResolvedAsset) {
const std::shared_ptr<const RenderPipelineAsset> resolvedAsset =
ResolveRenderPipelineAssetOrDefault(preferredAsset);
if (resolvedAsset != nullptr) {
if (std::unique_ptr<RenderPipeline> pipeline =
resolvedAsset->CreatePipeline()) {
if (outResolvedAsset != nullptr) {
*outResolvedAsset = resolvedAsset;
}
return pipeline;
}
}
const std::shared_ptr<const RenderPipelineAsset> defaultAsset =
ResolveRenderPipelineAssetOrDefault(nullptr);
if (defaultAsset != nullptr &&
defaultAsset != resolvedAsset) {
if (std::unique_ptr<RenderPipeline> pipeline =
defaultAsset->CreatePipeline()) {
if (outResolvedAsset != nullptr) {
*outResolvedAsset = defaultAsset;
}
return pipeline;
}
}
const std::shared_ptr<const RenderPipelineAsset> fallbackAsset =
CreateFallbackRenderPipelineAsset();
if (fallbackAsset != nullptr &&
fallbackAsset != resolvedAsset &&
fallbackAsset != defaultAsset) {
if (std::unique_ptr<RenderPipeline> pipeline =
fallbackAsset->CreatePipeline()) {
if (outResolvedAsset != nullptr) {
*outResolvedAsset = fallbackAsset;
}
return pipeline;
}
}
if (outResolvedAsset != nullptr) {
*outResolvedAsset =
fallbackAsset != nullptr
? fallbackAsset
: (defaultAsset != nullptr
? defaultAsset
: resolvedAsset);
}
return std::make_unique<Pipelines::ScriptableRenderPipelineHost>();
}
std::unique_ptr<NativeSceneRenderer> CreateNativeSceneRendererFromAsset(
const std::shared_ptr<const RenderPipelineAsset>& preferredAsset,
std::shared_ptr<const RenderPipelineAsset>* outResolvedAsset) {
if (std::unique_ptr<NativeSceneRenderer> sceneRenderer =
TryCreateNativeSceneRendererFromAsset(preferredAsset)) {
if (outResolvedAsset != nullptr) {
*outResolvedAsset = preferredAsset;
}
return sceneRenderer;
}
if (outResolvedAsset != nullptr) {
outResolvedAsset->reset();
}
return CreateDefaultNativeSceneRenderer();
}
std::unique_ptr<NativeSceneRenderer> CreateDefaultNativeSceneRenderer() {
return std::make_unique<Pipelines::BuiltinForwardPipeline>();
}
} // namespace Internal
} // namespace Rendering
} // namespace XCEngine