Files
XCEngine/engine/src/Rendering/Execution/SceneRenderer.cpp

229 lines
8.4 KiB
C++
Raw Normal View History

#include "Rendering/Execution/SceneRenderer.h"
#include "Components/CameraComponent.h"
#include "Rendering/Caches/FullscreenPassSurfaceCache.h"
#include "Rendering/Planning/CameraPostProcessPassFactory.h"
#include "Rendering/Planning/FinalColorPassFactory.h"
#include "Rendering/Planning/SceneRenderRequestUtils.h"
#include "Rendering/RenderPipelineAsset.h"
namespace XCEngine {
namespace Rendering {
namespace {
RenderSurface ConfigureFullscreenStageSurface(
const FullscreenPassSurfaceCache::SurfaceEntry& entry,
const RenderSurface& templateSurface,
bool copyDepthAttachment) {
RenderSurface surface = entry.surface;
if (copyDepthAttachment) {
surface.SetDepthAttachment(templateSurface.GetDepthAttachment());
if (templateSurface.HasClearColorOverride()) {
surface.SetClearColorOverride(templateSurface.GetClearColorOverride());
}
}
if (templateSurface.HasCustomRenderArea()) {
surface.SetRenderArea(templateSurface.GetRenderArea());
} else {
surface.ResetRenderArea();
}
surface.SetColorStateBefore(RHI::ResourceStates::Common);
surface.SetColorStateAfter(RHI::ResourceStates::PixelShaderResource);
return surface;
}
} // namespace
SceneRenderer::SceneRenderer() = default;
SceneRenderer::SceneRenderer(std::unique_ptr<RenderPipeline> pipeline)
: m_cameraRenderer(std::move(pipeline)) {
}
SceneRenderer::SceneRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset)
: m_cameraRenderer(std::move(pipelineAsset)) {
}
SceneRenderer::~SceneRenderer() = default;
void SceneRenderer::SetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
m_cameraRenderer.SetPipeline(std::move(pipeline));
}
void SceneRenderer::SetPipelineAsset(std::shared_ptr<const RenderPipelineAsset> pipelineAsset) {
m_cameraRenderer.SetPipelineAsset(std::move(pipelineAsset));
}
std::vector<CameraRenderRequest> SceneRenderer::BuildRenderRequests(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera,
const RenderContext& context,
const RenderSurface& surface) {
std::vector<CameraRenderRequest> requests =
m_requestPlanner.BuildRequests(scene, overrideCamera, context, surface);
ResolveCameraFinalColorPolicies(requests);
AttachFullscreenStageRequests(context, requests);
return requests;
}
bool SceneRenderer::Render(const CameraRenderRequest& request) {
return m_cameraRenderer.Render(request);
}
bool SceneRenderer::Render(const std::vector<CameraRenderRequest>& requests) {
if (requests.empty()) {
return false;
}
for (const CameraRenderRequest& request : requests) {
if (!request.IsValid()) {
return false;
}
}
std::vector<CameraRenderRequest> sortedRequests = requests;
SceneRenderRequestUtils::SortCameraRenderRequests(sortedRequests);
bool rendered = false;
for (const CameraRenderRequest& request : sortedRequests) {
if (!m_cameraRenderer.Render(request)) {
return false;
}
rendered = true;
}
return rendered;
}
bool SceneRenderer::Render(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera,
const RenderContext& context,
const RenderSurface& surface) {
return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
}
void SceneRenderer::PrepareOwnedFullscreenStageState(size_t requestCount) {
m_ownedPostProcessSequences.clear();
m_ownedPostProcessSequences.resize(requestCount);
m_ownedFinalOutputSequences.clear();
m_ownedFinalOutputSequences.resize(requestCount);
if (m_ownedFullscreenStageSurfaces.size() < requestCount) {
m_ownedFullscreenStageSurfaces.resize(requestCount);
}
for (size_t index = 0; index < requestCount; ++index) {
if (m_ownedFullscreenStageSurfaces[index] == nullptr) {
m_ownedFullscreenStageSurfaces[index] = std::make_unique<FullscreenPassSurfaceCache>();
}
}
}
void SceneRenderer::ResolveCameraFinalColorPolicies(
std::vector<CameraRenderRequest>& requests) const {
const RenderPipelineAsset* pipelineAsset = GetPipelineAsset();
const FinalColorSettings pipelineDefaults =
pipelineAsset != nullptr ? pipelineAsset->GetDefaultFinalColorSettings() : FinalColorSettings();
for (CameraRenderRequest& request : requests) {
if (request.camera == nullptr) {
continue;
}
request.finalColorPolicy = ResolveFinalColorPolicy(
pipelineDefaults,
&request.camera->GetFinalColorOverrides(),
nullptr);
}
}
void SceneRenderer::AttachFullscreenStageRequests(
const RenderContext& context,
std::vector<CameraRenderRequest>& requests) {
PrepareOwnedFullscreenStageState(requests.size());
for (size_t index = 0; index < requests.size(); ++index) {
CameraRenderRequest& request = requests[index];
if (request.camera == nullptr ||
request.context.device == nullptr ||
!HasValidColorTarget(request.surface)) {
continue;
}
std::unique_ptr<RenderPassSequence> postProcessSequence =
BuildCameraPostProcessPassSequence(request.camera->GetPostProcessPasses());
std::unique_ptr<RenderPassSequence> finalOutputSequence =
BuildFinalColorPassSequence(request.finalColorPolicy);
const bool hasPostProcess =
postProcessSequence != nullptr && postProcessSequence->GetPassCount() > 0u;
const bool hasFinalOutput =
finalOutputSequence != nullptr && finalOutputSequence->GetPassCount() > 0u;
if (!hasPostProcess && !hasFinalOutput) {
continue;
}
const std::vector<RHI::RHIResourceView*>& colorAttachments = request.surface.GetColorAttachments();
const RHI::Format colorFormat = colorAttachments[0]->GetFormat();
if (colorFormat == RHI::Format::Unknown) {
continue;
}
const size_t fullscreenSurfaceCount = hasPostProcess && hasFinalOutput ? 2u : 1u;
FullscreenPassSurfaceCache* surfaceCache = m_ownedFullscreenStageSurfaces[index].get();
if (surfaceCache == nullptr ||
!surfaceCache->EnsureSurfaces(
context,
request.surface.GetWidth(),
request.surface.GetHeight(),
colorFormat,
fullscreenSurfaceCount)) {
continue;
}
const FullscreenPassSurfaceCache::SurfaceEntry* sceneColorEntry = surfaceCache->GetSurfaceEntry(0u);
if (sceneColorEntry == nullptr || sceneColorEntry->shaderResourceView == nullptr) {
continue;
}
const FullscreenPassSurfaceCache::SurfaceEntry* postProcessOutputEntry =
hasPostProcess && hasFinalOutput ? surfaceCache->GetSurfaceEntry(1u) : nullptr;
if (hasPostProcess && hasFinalOutput &&
(postProcessOutputEntry == nullptr || postProcessOutputEntry->shaderResourceView == nullptr)) {
continue;
}
if (hasPostProcess) {
request.postProcess.sourceSurface =
ConfigureFullscreenStageSurface(*sceneColorEntry, request.surface, true);
request.postProcess.sourceColorView = sceneColorEntry->shaderResourceView;
request.postProcess.destinationSurface =
hasFinalOutput
? ConfigureFullscreenStageSurface(*postProcessOutputEntry, request.surface, false)
: request.surface;
m_ownedPostProcessSequences[index] = std::move(postProcessSequence);
request.postProcess.passes = m_ownedPostProcessSequences[index].get();
}
if (hasFinalOutput) {
const FullscreenPassSurfaceCache::SurfaceEntry* finalOutputSourceEntry =
hasPostProcess ? postProcessOutputEntry : sceneColorEntry;
request.finalOutput.sourceSurface =
hasPostProcess
? request.postProcess.destinationSurface
: ConfigureFullscreenStageSurface(*sceneColorEntry, request.surface, true);
request.finalOutput.sourceColorView = finalOutputSourceEntry->shaderResourceView;
request.finalOutput.destinationSurface = request.surface;
m_ownedFinalOutputSequences[index] = std::move(finalOutputSequence);
request.finalOutput.passes = m_ownedFinalOutputSequences[index].get();
}
}
}
} // namespace Rendering
} // namespace XCEngine