Harden render graph pass capture and feature source-color contract
This commit is contained in:
@@ -26,6 +26,7 @@ struct SceneRenderFeaturePassRenderGraphContext {
|
||||
const RenderSurface* sourceSurface = nullptr;
|
||||
RHI::RHIResourceView* sourceColorView = nullptr;
|
||||
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
|
||||
RenderGraphTextureHandle sourceColorTexture = {};
|
||||
std::vector<RenderGraphTextureHandle> colorTargets = {};
|
||||
RenderGraphTextureHandle depthTarget = {};
|
||||
RenderGraphTextureHandle mainDirectionalShadowTexture = {};
|
||||
|
||||
@@ -172,11 +172,13 @@ bool RecordRasterRenderPass(
|
||||
const RenderPassGraphIO& io) {
|
||||
RenderPass* const renderPass = &pass;
|
||||
const Containers::String passName = context.passName;
|
||||
const RenderContext* const renderContext = &context.renderContext;
|
||||
const RenderContext 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;
|
||||
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;
|
||||
@@ -192,6 +194,7 @@ bool RecordRasterRenderPass(
|
||||
renderContext,
|
||||
sceneData,
|
||||
surface,
|
||||
hasSourceSurface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
@@ -224,6 +227,7 @@ bool RecordRasterRenderPass(
|
||||
renderContext,
|
||||
sceneData,
|
||||
surface,
|
||||
hasSourceSurface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
@@ -239,12 +243,13 @@ bool RecordRasterRenderPass(
|
||||
return;
|
||||
}
|
||||
|
||||
const RenderSurface* resolvedSourceSurface = sourceSurface;
|
||||
const RenderSurface* resolvedSourceSurface =
|
||||
hasSourceSurface ? &sourceSurface : nullptr;
|
||||
RHI::RHIResourceView* resolvedSourceColorView = sourceColorView;
|
||||
RHI::ResourceStates resolvedSourceColorState = sourceColorState;
|
||||
RenderSurface graphManagedSourceSurface = {};
|
||||
if (!ResolveGraphManagedSourceSurface(
|
||||
sourceSurface,
|
||||
hasSourceSurface ? &sourceSurface : nullptr,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
sourceColorTexture,
|
||||
@@ -277,7 +282,7 @@ bool RecordRasterRenderPass(
|
||||
}
|
||||
|
||||
const RenderPassContext passContext = {
|
||||
*renderContext,
|
||||
renderContext,
|
||||
*resolvedSurface,
|
||||
*sceneData,
|
||||
resolvedSourceSurface,
|
||||
|
||||
@@ -94,11 +94,14 @@ bool BuiltinForwardPipeline::SupportsMainSceneRenderGraph() const {
|
||||
bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
const RenderPipelineMainSceneRenderGraphContext& context) {
|
||||
const Containers::String passName = context.passName;
|
||||
const RenderContext* const renderContext = &context.renderContext;
|
||||
const RenderSceneData* const sceneData = &context.sceneData;
|
||||
const RenderContext renderContext = context.renderContext;
|
||||
const std::shared_ptr<const RenderSceneData> sceneData =
|
||||
std::make_shared<RenderSceneData>(context.sceneData);
|
||||
const RenderSurface surfaceTemplate =
|
||||
BuildGraphManagedForwardSceneSurface(context.surfaceTemplate);
|
||||
const RenderSurface* const sourceSurface = context.sourceSurface;
|
||||
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 std::vector<RenderGraphTextureHandle> colorTargets = context.colorTargets;
|
||||
@@ -113,6 +116,7 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
graphExecutionState,
|
||||
renderContext,
|
||||
sceneData,
|
||||
hasSourceSurface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
@@ -124,7 +128,7 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
}
|
||||
|
||||
if (!graphExecutionState->initialized) {
|
||||
if (!Initialize(*renderContext)) {
|
||||
if (!Initialize(renderContext)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinForwardPipeline::RecordMainSceneRenderGraph failed during execution: Initialize returned false");
|
||||
@@ -135,10 +139,10 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
}
|
||||
|
||||
const FrameExecutionContext executionContext(
|
||||
*renderContext,
|
||||
renderContext,
|
||||
passContext.surface,
|
||||
*sceneData,
|
||||
sourceSurface,
|
||||
hasSourceSurface ? &sourceSurface : nullptr,
|
||||
sourceColorView,
|
||||
sourceColorState);
|
||||
if (!m_forwardSceneFeatureHost.Prepare(executionContext)) {
|
||||
@@ -177,12 +181,13 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
const SceneRenderFeaturePassRenderGraphContext featureContext = {
|
||||
context.graphBuilder,
|
||||
passName,
|
||||
*renderContext,
|
||||
renderContext,
|
||||
*sceneData,
|
||||
surfaceTemplate,
|
||||
sourceSurface,
|
||||
hasSourceSurface ? &sourceSurface : nullptr,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
{},
|
||||
colorTargets,
|
||||
depthTarget,
|
||||
mainDirectionalShadowTexture,
|
||||
@@ -214,6 +219,7 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
surfaceTemplate,
|
||||
renderContext,
|
||||
sceneData,
|
||||
hasSourceSurface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
@@ -245,6 +251,7 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
surfaceTemplate,
|
||||
renderContext,
|
||||
sceneData,
|
||||
hasSourceSurface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
@@ -259,10 +266,10 @@ bool BuiltinForwardPipeline::RecordMainSceneRenderGraph(
|
||||
}
|
||||
|
||||
const FrameExecutionContext executionContext(
|
||||
*renderContext,
|
||||
renderContext,
|
||||
surfaceTemplate,
|
||||
*sceneData,
|
||||
sourceSurface,
|
||||
hasSourceSurface ? &sourceSurface : nullptr,
|
||||
sourceColorView,
|
||||
sourceColorState);
|
||||
const RenderPassContext passContext =
|
||||
|
||||
@@ -131,6 +131,7 @@ bool SceneRenderFeatureHost::Record(
|
||||
context.sourceSurface,
|
||||
context.sourceColorView,
|
||||
context.sourceColorState,
|
||||
context.sourceColorTexture,
|
||||
context.colorTargets,
|
||||
context.depthTarget,
|
||||
context.mainDirectionalShadowTexture,
|
||||
|
||||
@@ -1,98 +1,62 @@
|
||||
#include "Rendering/SceneRenderFeaturePass.h"
|
||||
|
||||
#include "Rendering/Graph/RenderGraph.h"
|
||||
#include "Rendering/Internal/RenderPassGraphUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
bool SceneRenderFeaturePass::RecordRenderGraph(
|
||||
const SceneRenderFeaturePassRenderGraphContext& context) {
|
||||
SceneRenderFeaturePass* const featurePass = this;
|
||||
const Containers::String passName = context.passName;
|
||||
const RenderContext* const renderContext = &context.renderContext;
|
||||
const RenderSceneData* const sceneData = &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 std::vector<RenderGraphTextureHandle> colorTargets = context.colorTargets;
|
||||
const RenderGraphTextureHandle depthTarget = context.depthTarget;
|
||||
const bool clearAttachments = context.clearAttachments;
|
||||
bool* const executionSucceeded = context.executionSucceeded;
|
||||
const SceneRenderFeaturePassBeginCallback beginPassCallback = context.beginPassCallback;
|
||||
const SceneRenderFeaturePassEndCallback endPassCallback = context.endPassCallback;
|
||||
|
||||
context.graphBuilder.AddRasterPass(
|
||||
passName,
|
||||
[featurePass,
|
||||
renderContext,
|
||||
sceneData,
|
||||
surface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
colorTargets,
|
||||
depthTarget,
|
||||
clearAttachments,
|
||||
executionSucceeded,
|
||||
beginPassCallback,
|
||||
endPassCallback](
|
||||
RenderGraphPassBuilder& passBuilder) {
|
||||
for (RenderGraphTextureHandle colorTarget : colorTargets) {
|
||||
if (colorTarget.IsValid()) {
|
||||
passBuilder.WriteTexture(colorTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (depthTarget.IsValid()) {
|
||||
passBuilder.WriteDepthTexture(depthTarget);
|
||||
}
|
||||
|
||||
passBuilder.SetExecuteCallback(
|
||||
[featurePass,
|
||||
renderContext,
|
||||
sceneData,
|
||||
surface,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState,
|
||||
clearAttachments,
|
||||
executionSucceeded,
|
||||
beginPassCallback,
|
||||
endPassCallback](
|
||||
const RenderGraphExecutionContext&) {
|
||||
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameExecutionContext executionContext(
|
||||
*renderContext,
|
||||
surface,
|
||||
*sceneData,
|
||||
sourceSurface,
|
||||
sourceColorView,
|
||||
sourceColorState);
|
||||
const RenderPassContext passContext =
|
||||
BuildRenderPassContext(executionContext);
|
||||
if (beginPassCallback &&
|
||||
!beginPassCallback(passContext, clearAttachments)) {
|
||||
if (executionSucceeded != nullptr) {
|
||||
*executionSucceeded = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const bool executeResult = featurePass->Execute(passContext);
|
||||
if (endPassCallback) {
|
||||
endPassCallback(passContext);
|
||||
}
|
||||
|
||||
if (executionSucceeded != nullptr) {
|
||||
*executionSucceeded = executeResult;
|
||||
}
|
||||
});
|
||||
const bool usesSourceColor = context.sourceColorTexture.IsValid();
|
||||
const bool hasSourceSurfaceTemplate =
|
||||
context.sourceSurface != nullptr || usesSourceColor;
|
||||
const RenderSurface sourceSurfaceTemplate =
|
||||
context.sourceSurface != nullptr
|
||||
? *context.sourceSurface
|
||||
: (usesSourceColor ? context.surface : RenderSurface());
|
||||
const bool writesColor =
|
||||
std::any_of(
|
||||
context.colorTargets.begin(),
|
||||
context.colorTargets.end(),
|
||||
[](RenderGraphTextureHandle handle) {
|
||||
return handle.IsValid();
|
||||
});
|
||||
const RenderPassGraphBeginCallback beginPassCallback =
|
||||
context.beginPassCallback
|
||||
? RenderPassGraphBeginCallback(
|
||||
[beginPass = context.beginPassCallback,
|
||||
clearAttachments = context.clearAttachments](
|
||||
const RenderPassContext& passContext) {
|
||||
return beginPass(passContext, clearAttachments);
|
||||
})
|
||||
: RenderPassGraphBeginCallback();
|
||||
const RenderPassRenderGraphContext passContext = {
|
||||
context.graphBuilder,
|
||||
context.passName,
|
||||
context.renderContext,
|
||||
context.sceneData,
|
||||
context.surface,
|
||||
hasSourceSurfaceTemplate ? &sourceSurfaceTemplate : nullptr,
|
||||
context.sourceColorView,
|
||||
context.sourceColorState,
|
||||
context.sourceColorTexture,
|
||||
context.colorTargets,
|
||||
context.depthTarget,
|
||||
context.executionSucceeded,
|
||||
beginPassCallback,
|
||||
context.endPassCallback,
|
||||
context.blackboard
|
||||
};
|
||||
return Internal::RecordRasterRenderPass(
|
||||
*this,
|
||||
passContext,
|
||||
{
|
||||
usesSourceColor,
|
||||
writesColor,
|
||||
context.depthTarget.IsValid()
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -452,8 +452,20 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Execute(const RenderPassContext&) override {
|
||||
bool Execute(const RenderPassContext& context) override {
|
||||
++executeCallCount;
|
||||
lastHasSourceSurface = context.sourceSurface != nullptr;
|
||||
lastSourceColorView = context.sourceColorView;
|
||||
if (context.sourceSurface != nullptr) {
|
||||
lastSourceSurfaceWidth = context.sourceSurface->GetWidth();
|
||||
lastSourceSurfaceHeight = context.sourceSurface->GetHeight();
|
||||
lastSourceSurfaceRenderAreaWidth =
|
||||
context.sourceSurface->GetRenderAreaWidth();
|
||||
lastSourceSurfaceRenderAreaHeight =
|
||||
context.sourceSurface->GetRenderAreaHeight();
|
||||
lastSourceSurfaceAutoTransitionEnabled =
|
||||
context.sourceSurface->IsAutoTransitionEnabled();
|
||||
}
|
||||
RecordEvent("Execute");
|
||||
return true;
|
||||
}
|
||||
@@ -461,6 +473,7 @@ public:
|
||||
bool RecordRenderGraph(
|
||||
const SceneRenderFeaturePassRenderGraphContext& context) override {
|
||||
++recordGraphCallCount;
|
||||
lastReceivedSourceColorTextureValid = context.sourceColorTexture.IsValid();
|
||||
RecordEvent("RecordGraph");
|
||||
return SceneRenderFeaturePass::RecordRenderGraph(context);
|
||||
}
|
||||
@@ -471,6 +484,14 @@ public:
|
||||
size_t executeCallCount = 0u;
|
||||
size_t recordGraphCallCount = 0u;
|
||||
size_t shutdownCallCount = 0u;
|
||||
bool lastHasSourceSurface = false;
|
||||
uint32_t lastSourceSurfaceWidth = 0u;
|
||||
uint32_t lastSourceSurfaceHeight = 0u;
|
||||
uint32_t lastSourceSurfaceRenderAreaWidth = 0u;
|
||||
uint32_t lastSourceSurfaceRenderAreaHeight = 0u;
|
||||
bool lastSourceSurfaceAutoTransitionEnabled = true;
|
||||
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
|
||||
bool lastReceivedSourceColorTextureValid = false;
|
||||
|
||||
private:
|
||||
void RecordEvent(const char* suffix) {
|
||||
@@ -719,6 +740,7 @@ TEST(SceneRenderFeaturePass_Test, RecordsDefaultGraphPassAndExecutesWrappedCallb
|
||||
nullptr,
|
||||
nullptr,
|
||||
ResourceStates::Common,
|
||||
{},
|
||||
{ colorTarget },
|
||||
depthTarget,
|
||||
{},
|
||||
@@ -756,6 +778,107 @@ TEST(SceneRenderFeaturePass_Test, RecordsDefaultGraphPassAndExecutesWrappedCallb
|
||||
"FeatureGraph:Execute" }));
|
||||
}
|
||||
|
||||
TEST(SceneRenderFeaturePass_Test, ReadsSourceColorTextureAndCopiesSourceSurfaceTemplateForGraphExecution) {
|
||||
TestSceneRenderFeaturePass feature(
|
||||
SceneRenderInjectionPoint::BeforeOpaque,
|
||||
true,
|
||||
nullptr,
|
||||
"FeatureReadSource");
|
||||
|
||||
RenderGraph graph = {};
|
||||
RenderGraphBuilder graphBuilder(graph);
|
||||
|
||||
RenderGraphTextureDesc colorDesc = {};
|
||||
colorDesc.width = 96u;
|
||||
colorDesc.height = 48u;
|
||||
colorDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
colorDesc.textureType = static_cast<uint32_t>(XCEngine::RHI::TextureType::Texture2D);
|
||||
colorDesc.sampleCount = 1u;
|
||||
|
||||
TestResourceView sourceRenderTargetView(
|
||||
ResourceViewType::RenderTarget,
|
||||
ResourceViewDimension::Texture2D,
|
||||
Format::R8G8B8A8_UNorm);
|
||||
TestResourceView sourceShaderView(
|
||||
ResourceViewType::ShaderResource,
|
||||
ResourceViewDimension::Texture2D,
|
||||
Format::R8G8B8A8_UNorm);
|
||||
TestResourceView outputView(
|
||||
ResourceViewType::RenderTarget,
|
||||
ResourceViewDimension::Texture2D,
|
||||
Format::R8G8B8A8_UNorm);
|
||||
const RenderGraphImportedTextureOptions graphManagedImport = {
|
||||
ResourceStates::Common,
|
||||
ResourceStates::Common,
|
||||
true
|
||||
};
|
||||
const RenderGraphTextureHandle sourceColor =
|
||||
graphBuilder.ImportTexture("SceneColor", colorDesc, &sourceRenderTargetView, graphManagedImport);
|
||||
const RenderGraphTextureHandle outputColor =
|
||||
graphBuilder.ImportTexture("OutputColor", colorDesc, &outputView, graphManagedImport);
|
||||
|
||||
RenderContext renderContext = {};
|
||||
MockForwardCommandList commandList;
|
||||
renderContext.commandList = &commandList;
|
||||
|
||||
RenderSceneData sceneData = {};
|
||||
RenderSurface outputSurface(96u, 48u);
|
||||
outputSurface.SetColorAttachment(&outputView);
|
||||
outputSurface.SetAutoTransitionEnabled(false);
|
||||
|
||||
RenderSurface sourceSurfaceTemplate(96u, 48u);
|
||||
sourceSurfaceTemplate.SetColorAttachment(&sourceRenderTargetView);
|
||||
sourceSurfaceTemplate.SetRenderArea(XCEngine::Math::RectInt(11, 7, 85, 41));
|
||||
|
||||
bool executionSucceeded = true;
|
||||
const SceneRenderFeaturePassRenderGraphContext context = {
|
||||
graphBuilder,
|
||||
"FeatureReadSourcePass",
|
||||
renderContext,
|
||||
sceneData,
|
||||
outputSurface,
|
||||
&sourceSurfaceTemplate,
|
||||
&sourceShaderView,
|
||||
ResourceStates::Common,
|
||||
sourceColor,
|
||||
{ outputColor },
|
||||
{},
|
||||
{},
|
||||
false,
|
||||
&executionSucceeded,
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
ASSERT_TRUE(feature.RecordRenderGraph(context));
|
||||
|
||||
sourceSurfaceTemplate = RenderSurface(8u, 8u);
|
||||
sourceSurfaceTemplate.SetRenderArea(XCEngine::Math::RectInt(1, 2, 8, 8));
|
||||
|
||||
CompiledRenderGraph compiledGraph = {};
|
||||
String errorMessage;
|
||||
ASSERT_TRUE(RenderGraphCompiler::Compile(graph, compiledGraph, &errorMessage))
|
||||
<< errorMessage.CStr();
|
||||
|
||||
RenderGraphTextureLifetime lifetime = {};
|
||||
ASSERT_TRUE(compiledGraph.TryGetTextureLifetime(sourceColor, lifetime));
|
||||
EXPECT_TRUE(lifetime.used);
|
||||
EXPECT_EQ(lifetime.firstPassIndex, 0u);
|
||||
EXPECT_EQ(lifetime.lastPassIndex, 0u);
|
||||
|
||||
ASSERT_TRUE(RenderGraphExecutor::Execute(compiledGraph, renderContext, &errorMessage))
|
||||
<< errorMessage.CStr();
|
||||
EXPECT_TRUE(executionSucceeded);
|
||||
EXPECT_TRUE(feature.lastReceivedSourceColorTextureValid);
|
||||
EXPECT_TRUE(feature.lastHasSourceSurface);
|
||||
EXPECT_EQ(feature.lastSourceSurfaceWidth, 96u);
|
||||
EXPECT_EQ(feature.lastSourceSurfaceHeight, 48u);
|
||||
EXPECT_EQ(feature.lastSourceSurfaceRenderAreaWidth, 85u);
|
||||
EXPECT_EQ(feature.lastSourceSurfaceRenderAreaHeight, 41u);
|
||||
EXPECT_FALSE(feature.lastSourceSurfaceAutoTransitionEnabled);
|
||||
EXPECT_NE(feature.lastSourceColorView, nullptr);
|
||||
}
|
||||
|
||||
TEST(BuiltinForwardPipeline_Test, RegistersBuiltinDefaultForwardSceneFeatures) {
|
||||
BuiltinForwardPipeline pipeline;
|
||||
|
||||
@@ -920,6 +1043,7 @@ TEST(SceneRenderFeatureHost_Test, RecordsActiveInjectionPointFeaturesIntoRenderG
|
||||
nullptr,
|
||||
nullptr,
|
||||
ResourceStates::Common,
|
||||
{},
|
||||
{ colorTarget },
|
||||
depthTarget,
|
||||
{},
|
||||
|
||||
Reference in New Issue
Block a user