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

310 lines
11 KiB
C++
Raw Normal View History

2026-04-14 17:16:08 +08:00
#include "Rendering/Internal/RenderPassGraphUtils.h"
#include "Rendering/FrameData/RenderSceneData.h"
#include "Rendering/Graph/RenderGraph.h"
#include <algorithm>
#include <memory>
namespace XCEngine {
namespace Rendering {
namespace Internal {
namespace {
RenderSurface BuildGraphManagedImportedSurface(
const RenderSurface& templateSurface,
RHI::ResourceStates colorStateBefore,
RHI::ResourceStates colorStateAfter) {
RenderSurface surface = templateSurface;
surface.SetAutoTransitionEnabled(false);
surface.SetColorStateBefore(colorStateBefore);
surface.SetColorStateAfter(colorStateAfter);
return surface;
}
RenderSurface BuildGraphManagedPassSurface(
const RenderSurface& templateSurface) {
RenderSurface surface = templateSurface;
surface.SetAutoTransitionEnabled(false);
return surface;
}
bool ResolveGraphManagedSourceSurface(
const RenderSurface* sourceSurfaceTemplate,
RHI::RHIResourceView* sourceColorView,
RHI::ResourceStates sourceColorState,
RenderGraphTextureHandle sourceColorTexture,
const RenderGraphExecutionContext& graphContext,
const RenderPassGraphIO& io,
const RenderSurface*& outSourceSurface,
RHI::RHIResourceView*& outSourceColorView,
RHI::ResourceStates& outSourceColorState,
RenderSurface& outGraphManagedSourceSurface) {
outSourceSurface = sourceSurfaceTemplate;
outSourceColorView = sourceColorView;
outSourceColorState = sourceColorState;
if (!io.readSourceColor ||
!sourceColorTexture.IsValid() ||
!graphContext.OwnsTextureTransitions(sourceColorTexture)) {
return true;
}
if (graphContext.IsTransientTexture(sourceColorTexture)) {
if (sourceSurfaceTemplate == nullptr) {
return false;
}
RHI::RHIResourceView* renderTargetView =
graphContext.ResolveTextureView(
sourceColorTexture,
RenderGraphTextureViewType::RenderTarget);
RHI::RHIResourceView* shaderResourceView =
graphContext.ResolveTextureView(
sourceColorTexture,
RenderGraphTextureViewType::ShaderResource);
if (renderTargetView == nullptr || shaderResourceView == nullptr) {
return false;
}
outGraphManagedSourceSurface = *sourceSurfaceTemplate;
outGraphManagedSourceSurface.SetColorAttachment(renderTargetView);
outGraphManagedSourceSurface.SetAutoTransitionEnabled(false);
outGraphManagedSourceSurface.SetColorStateBefore(RHI::ResourceStates::PixelShaderResource);
outGraphManagedSourceSurface.SetColorStateAfter(RHI::ResourceStates::PixelShaderResource);
outSourceSurface = &outGraphManagedSourceSurface;
outSourceColorView = shaderResourceView;
outSourceColorState = RHI::ResourceStates::PixelShaderResource;
return true;
}
if (sourceSurfaceTemplate != nullptr) {
outGraphManagedSourceSurface =
BuildGraphManagedImportedSurface(
*sourceSurfaceTemplate,
RHI::ResourceStates::PixelShaderResource,
RHI::ResourceStates::PixelShaderResource);
outSourceSurface = &outGraphManagedSourceSurface;
}
outSourceColorState = RHI::ResourceStates::PixelShaderResource;
return true;
}
bool ResolveGraphManagedOutputSurface(
const RenderSurface& surfaceTemplate,
const std::vector<RenderGraphTextureHandle>& colorTargets,
RenderGraphTextureHandle depthTarget,
const RenderGraphExecutionContext& graphContext,
const RenderPassGraphIO& io,
const RenderSurface*& outSurface,
RenderSurface& outGraphManagedSurface) {
outSurface = &surfaceTemplate;
const bool ownsAnyColorTransitions =
io.writeColor &&
std::any_of(
colorTargets.begin(),
colorTargets.end(),
[&](RenderGraphTextureHandle texture) {
return texture.IsValid() &&
graphContext.OwnsTextureTransitions(texture);
});
const bool ownsDepthTransitions =
io.writeDepth &&
depthTarget.IsValid() &&
graphContext.OwnsTextureTransitions(depthTarget);
if (!ownsAnyColorTransitions && !ownsDepthTransitions) {
return true;
}
outGraphManagedSurface = BuildGraphManagedPassSurface(surfaceTemplate);
if (ownsAnyColorTransitions) {
std::vector<RHI::RHIResourceView*> colorAttachments =
surfaceTemplate.GetColorAttachments();
if (colorAttachments.size() < colorTargets.size()) {
colorAttachments.resize(colorTargets.size(), nullptr);
}
for (size_t colorIndex = 0u; colorIndex < colorTargets.size(); ++colorIndex) {
const RenderGraphTextureHandle colorTarget = colorTargets[colorIndex];
if (!colorTarget.IsValid() ||
!graphContext.OwnsTextureTransitions(colorTarget) ||
!graphContext.IsTransientTexture(colorTarget)) {
continue;
}
colorAttachments[colorIndex] =
graphContext.ResolveTextureView(
colorTarget,
RenderGraphTextureViewType::RenderTarget);
if (colorAttachments[colorIndex] == nullptr) {
return false;
}
}
outGraphManagedSurface.SetColorAttachments(colorAttachments);
}
if (ownsDepthTransitions &&
graphContext.IsTransientTexture(depthTarget)) {
RHI::RHIResourceView* depthAttachment =
graphContext.ResolveTextureView(
depthTarget,
RenderGraphTextureViewType::DepthStencil);
if (depthAttachment == nullptr) {
return false;
}
outGraphManagedSurface.SetDepthAttachment(depthAttachment);
}
outSurface = &outGraphManagedSurface;
return true;
}
} // namespace
bool RecordRasterRenderPass(
RenderPass& pass,
const RenderPassRenderGraphContext& context,
const RenderPassGraphIO& io) {
RenderPass* const renderPass = &pass;
const Containers::String passName = context.passName;
const RenderContext* const renderContext = &context.renderContext;
const std::shared_ptr<const RenderSceneData> sceneData =
std::make_shared<RenderSceneData>(context.sceneData);
const RenderSurface surface = context.surface;
const RenderSurface* const sourceSurface = context.sourceSurface;
RHI::RHIResourceView* const sourceColorView = context.sourceColorView;
const RHI::ResourceStates sourceColorState = context.sourceColorState;
const RenderGraphTextureHandle sourceColorTexture = context.sourceColorTexture;
const std::vector<RenderGraphTextureHandle> colorTargets = context.colorTargets;
const RenderGraphTextureHandle depthTarget = context.depthTarget;
bool* const executionSucceeded = context.executionSucceeded;
const RenderPassGraphBeginCallback beginPassCallback = context.beginPassCallback;
const RenderPassGraphEndCallback endPassCallback = context.endPassCallback;
context.graphBuilder.AddRasterPass(
passName,
[renderPass,
renderContext,
sceneData,
surface,
sourceSurface,
sourceColorView,
sourceColorState,
sourceColorTexture,
colorTargets,
depthTarget,
executionSucceeded,
beginPassCallback,
endPassCallback,
io](
RenderGraphPassBuilder& passBuilder) {
if (io.readSourceColor && sourceColorTexture.IsValid()) {
passBuilder.ReadTexture(sourceColorTexture);
}
if (io.writeColor) {
for (RenderGraphTextureHandle colorTarget : colorTargets) {
if (colorTarget.IsValid()) {
passBuilder.WriteTexture(colorTarget);
}
}
}
if (io.writeDepth && depthTarget.IsValid()) {
passBuilder.WriteDepthTexture(depthTarget);
}
passBuilder.SetExecuteCallback(
[renderPass,
renderContext,
sceneData,
surface,
sourceSurface,
sourceColorView,
sourceColorState,
sourceColorTexture,
colorTargets,
depthTarget,
executionSucceeded,
beginPassCallback,
endPassCallback,
io](
const RenderGraphExecutionContext& executionContext) {
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
return;
}
const RenderSurface* resolvedSourceSurface = sourceSurface;
RHI::RHIResourceView* resolvedSourceColorView = sourceColorView;
RHI::ResourceStates resolvedSourceColorState = sourceColorState;
RenderSurface graphManagedSourceSurface = {};
if (!ResolveGraphManagedSourceSurface(
sourceSurface,
sourceColorView,
sourceColorState,
sourceColorTexture,
executionContext,
io,
resolvedSourceSurface,
resolvedSourceColorView,
resolvedSourceColorState,
graphManagedSourceSurface)) {
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return;
}
const RenderSurface* resolvedSurface = &surface;
RenderSurface graphManagedSurface = {};
if (!ResolveGraphManagedOutputSurface(
surface,
colorTargets,
depthTarget,
executionContext,
io,
resolvedSurface,
graphManagedSurface)) {
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return;
}
const RenderPassContext passContext = {
*renderContext,
*resolvedSurface,
*sceneData,
resolvedSourceSurface,
resolvedSourceColorView,
resolvedSourceColorState
};
if (beginPassCallback &&
!beginPassCallback(passContext)) {
if (executionSucceeded != nullptr) {
*executionSucceeded = false;
}
return;
}
const bool executeResult = renderPass->Execute(passContext);
if (endPassCallback) {
endPassCallback(passContext);
}
if (executionSucceeded != nullptr) {
*executionSucceeded = executeResult;
}
});
});
return true;
}
} // namespace Internal
} // namespace Rendering
} // namespace XCEngine