319 lines
12 KiB
C++
319 lines
12 KiB
C++
#include <XCEngine/Rendering/RenderPassGraphContract.h>
|
|
|
|
#include "Rendering/Execution/Internal/CameraFrameGraph/SurfaceUtils.h"
|
|
#include "Rendering/FrameData/RenderSceneData.h"
|
|
#include "Rendering/Graph/RenderGraph.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
namespace XCEngine {
|
|
namespace Rendering {
|
|
namespace {
|
|
|
|
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 RecordCallbackRasterRenderPass(
|
|
const RenderPassRenderGraphContext& context,
|
|
const RenderPassGraphIO& io,
|
|
RenderPassGraphExecutePassCallback executePassCallback,
|
|
std::vector<RenderGraphTextureHandle> additionalReadTextures) {
|
|
if (!executePassCallback) {
|
|
return false;
|
|
}
|
|
|
|
const Containers::String passName = context.passName;
|
|
const RenderContext renderContext = context.renderContext;
|
|
const std::shared_ptr<const RenderSceneData> sceneData =
|
|
std::make_shared<RenderSceneData>(context.sceneData);
|
|
const RenderSurface surface = context.surface;
|
|
const bool hasSourceSurface = context.sourceSurface != nullptr;
|
|
const RenderSurface sourceSurface =
|
|
hasSourceSurface ? *context.sourceSurface : RenderSurface();
|
|
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,
|
|
[renderContext,
|
|
sceneData,
|
|
surface,
|
|
hasSourceSurface,
|
|
sourceSurface,
|
|
sourceColorView,
|
|
sourceColorState,
|
|
sourceColorTexture,
|
|
colorTargets,
|
|
depthTarget,
|
|
executionSucceeded,
|
|
beginPassCallback,
|
|
endPassCallback,
|
|
executePassCallback,
|
|
additionalReadTextures,
|
|
io](
|
|
RenderGraphPassBuilder& passBuilder) {
|
|
if (io.readSourceColor && sourceColorTexture.IsValid()) {
|
|
passBuilder.ReadTexture(sourceColorTexture);
|
|
}
|
|
|
|
for (RenderGraphTextureHandle readTexture : additionalReadTextures) {
|
|
if (readTexture.IsValid()) {
|
|
passBuilder.ReadTexture(readTexture);
|
|
}
|
|
}
|
|
|
|
if (io.writeColor) {
|
|
for (RenderGraphTextureHandle colorTarget : colorTargets) {
|
|
if (colorTarget.IsValid()) {
|
|
passBuilder.WriteTexture(colorTarget);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (io.writeDepth && depthTarget.IsValid()) {
|
|
passBuilder.WriteDepthTexture(depthTarget);
|
|
}
|
|
|
|
passBuilder.SetExecuteCallback(
|
|
[renderContext,
|
|
sceneData,
|
|
surface,
|
|
hasSourceSurface,
|
|
sourceSurface,
|
|
sourceColorView,
|
|
sourceColorState,
|
|
sourceColorTexture,
|
|
colorTargets,
|
|
depthTarget,
|
|
executionSucceeded,
|
|
beginPassCallback,
|
|
endPassCallback,
|
|
executePassCallback,
|
|
io](
|
|
const RenderGraphExecutionContext& executionContext) {
|
|
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
|
|
return;
|
|
}
|
|
|
|
const RenderSurface* resolvedSourceSurface =
|
|
hasSourceSurface ? &sourceSurface : nullptr;
|
|
RHI::RHIResourceView* resolvedSourceColorView = sourceColorView;
|
|
RHI::ResourceStates resolvedSourceColorState = sourceColorState;
|
|
RenderSurface graphManagedSourceSurface = {};
|
|
if (!ResolveGraphManagedSourceSurface(
|
|
hasSourceSurface ? &sourceSurface : nullptr,
|
|
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 = executePassCallback(passContext);
|
|
if (endPassCallback) {
|
|
endPassCallback(passContext);
|
|
}
|
|
if (executionSucceeded != nullptr) {
|
|
*executionSucceeded = executeResult;
|
|
}
|
|
});
|
|
});
|
|
return true;
|
|
}
|
|
|
|
bool RecordRasterRenderPass(
|
|
RenderPass& pass,
|
|
const RenderPassRenderGraphContext& context,
|
|
const RenderPassGraphIO& io) {
|
|
return RecordCallbackRasterRenderPass(
|
|
context,
|
|
io,
|
|
[&pass](const RenderPassContext& passContext) {
|
|
return pass.Execute(passContext);
|
|
});
|
|
}
|
|
|
|
} // namespace Rendering
|
|
} // namespace XCEngine
|