Add render graph depth access semantics

This commit is contained in:
2026-04-14 13:56:08 +08:00
parent 9950e0a44f
commit 87bf83451b
7 changed files with 93 additions and 5 deletions

View File

@@ -38,6 +38,7 @@ private:
struct TextureAccess {
RenderGraphTextureHandle texture = {};
RenderGraphAccessMode mode = RenderGraphAccessMode::Read;
RenderGraphTextureAspect aspect = RenderGraphTextureAspect::Color;
};
struct PassNode {
@@ -60,6 +61,8 @@ class RenderGraphPassBuilder {
public:
void ReadTexture(RenderGraphTextureHandle texture);
void WriteTexture(RenderGraphTextureHandle texture);
void ReadDepthTexture(RenderGraphTextureHandle texture);
void WriteDepthTexture(RenderGraphTextureHandle texture);
void SetExecuteCallback(RenderGraphExecuteCallback callback);
private:

View File

@@ -31,6 +31,7 @@ private:
struct CompiledTextureAccess {
RenderGraphTextureHandle texture = {};
RenderGraphAccessMode mode = RenderGraphAccessMode::Read;
RenderGraphTextureAspect aspect = RenderGraphTextureAspect::Color;
RHI::ResourceStates requiredState = RHI::ResourceStates::Common;
};

View File

@@ -35,6 +35,11 @@ enum class RenderGraphAccessMode : Core::uint8 {
Write = 1
};
enum class RenderGraphTextureAspect : Core::uint8 {
Color = 0,
Depth = 1
};
enum class RenderGraphTextureViewType : Core::uint8 {
RenderTarget = 0,
ShaderResource = 1

View File

@@ -217,7 +217,7 @@ void ReadRenderGraphSurface(
}
if (surface.depthTexture.IsValid()) {
passBuilder.ReadTexture(surface.depthTexture);
passBuilder.ReadDepthTexture(surface.depthTexture);
}
}
@@ -241,7 +241,7 @@ void WriteRenderGraphSurface(
}
if (surface.depthTexture.IsValid()) {
passBuilder.WriteTexture(surface.depthTexture);
passBuilder.WriteDepthTexture(surface.depthTexture);
}
}

View File

@@ -25,6 +25,7 @@ void RenderGraphPassBuilder::ReadTexture(RenderGraphTextureHandle texture) {
RenderGraph::TextureAccess access = {};
access.texture = texture;
access.mode = RenderGraphAccessMode::Read;
access.aspect = RenderGraphTextureAspect::Color;
m_graph->m_passes[m_passHandle.index].accesses.push_back(access);
}
@@ -36,6 +37,31 @@ void RenderGraphPassBuilder::WriteTexture(RenderGraphTextureHandle texture) {
RenderGraph::TextureAccess access = {};
access.texture = texture;
access.mode = RenderGraphAccessMode::Write;
access.aspect = RenderGraphTextureAspect::Color;
m_graph->m_passes[m_passHandle.index].accesses.push_back(access);
}
void RenderGraphPassBuilder::ReadDepthTexture(RenderGraphTextureHandle texture) {
if (m_graph == nullptr || !m_passHandle.IsValid()) {
return;
}
RenderGraph::TextureAccess access = {};
access.texture = texture;
access.mode = RenderGraphAccessMode::Read;
access.aspect = RenderGraphTextureAspect::Depth;
m_graph->m_passes[m_passHandle.index].accesses.push_back(access);
}
void RenderGraphPassBuilder::WriteDepthTexture(RenderGraphTextureHandle texture) {
if (m_graph == nullptr || !m_passHandle.IsValid()) {
return;
}
RenderGraph::TextureAccess access = {};
access.texture = texture;
access.mode = RenderGraphAccessMode::Write;
access.aspect = RenderGraphTextureAspect::Depth;
m_graph->m_passes[m_passHandle.index].accesses.push_back(access);
}

View File

@@ -10,13 +10,24 @@ namespace {
RHI::ResourceStates ResolveRequiredState(
RenderGraphPassType passType,
RenderGraphAccessMode accessMode) {
RenderGraphAccessMode accessMode,
RenderGraphTextureAspect aspect) {
if (accessMode == RenderGraphAccessMode::Write) {
if (passType == RenderGraphPassType::Raster &&
aspect == RenderGraphTextureAspect::Depth) {
return RHI::ResourceStates::DepthWrite;
}
return passType == RenderGraphPassType::Compute
? RHI::ResourceStates::UnorderedAccess
: RHI::ResourceStates::RenderTarget;
}
if (passType == RenderGraphPassType::Raster &&
aspect == RenderGraphTextureAspect::Depth) {
return RHI::ResourceStates::DepthRead;
}
return passType == RenderGraphPassType::Compute
? RHI::ResourceStates::GenericRead
: RHI::ResourceStates::PixelShaderResource;
@@ -261,8 +272,9 @@ bool RenderGraphCompiler::Compile(
CompiledRenderGraph::CompiledTextureAccess compiledAccess = {};
compiledAccess.texture = access.texture;
compiledAccess.mode = access.mode;
compiledAccess.aspect = access.aspect;
compiledAccess.requiredState =
ResolveRequiredState(sourcePass.type, access.mode);
ResolveRequiredState(sourcePass.type, access.mode, access.aspect);
compiledPass.accesses.push_back(compiledAccess);
}
compiledPass.executeCallback = sourcePass.executeCallback;
@@ -280,7 +292,7 @@ bool RenderGraphCompiler::Compile(
lifetime.lastPassIndex = compiledPassIndex;
const RHI::ResourceStates accessState =
ResolveRequiredState(sourcePass.type, access.mode);
ResolveRequiredState(sourcePass.type, access.mode, access.aspect);
if (!transitionPlan.hasFirstAccessState) {
transitionPlan.hasFirstAccessState = true;
transitionPlan.firstAccessState = accessState;

View File

@@ -279,6 +279,17 @@ RenderGraphTextureDesc BuildTestTextureDesc() {
return desc;
}
RenderGraphTextureDesc BuildTestDepthTextureDesc() {
RenderGraphTextureDesc desc = {};
desc.width = 1024u;
desc.height = 1024u;
desc.format = static_cast<XCEngine::Core::uint32>(Format::D24_UNorm_S8_UInt);
desc.textureType = static_cast<XCEngine::Core::uint32>(TextureType::Texture2D);
desc.sampleCount = 1u;
desc.sampleQuality = 0u;
return desc;
}
} // namespace
TEST(RenderGraph_Test, CompilesDeclaredPassOrderAndTracksTextureLifetimes) {
@@ -533,6 +544,36 @@ TEST(RenderGraph_Test, RejectsGraphOwnedImportedTextureWithoutView) {
EXPECT_FALSE(errorMessage.Empty());
}
TEST(RenderGraph_Test, TracksDepthAttachmentTransitionPlan) {
RenderGraph graph;
RenderGraphBuilder builder(graph);
const RenderGraphTextureDesc depthDesc = BuildTestDepthTextureDesc();
const RenderGraphTextureHandle depthTexture =
builder.CreateTransientTexture("SceneDepth", depthDesc);
builder.AddRasterPass(
"DepthPrepass",
[&](RenderGraphPassBuilder& pass) {
pass.WriteDepthTexture(depthTexture);
});
CompiledRenderGraph compiledGraph;
XCEngine::Containers::String errorMessage;
ASSERT_TRUE(RenderGraphCompiler::Compile(graph, compiledGraph, &errorMessage))
<< errorMessage.CStr();
RenderGraphTextureTransitionPlan transitionPlan = {};
ASSERT_TRUE(compiledGraph.TryGetTextureTransitionPlan(depthTexture, transitionPlan));
EXPECT_TRUE(transitionPlan.graphOwnsTransitions);
EXPECT_TRUE(transitionPlan.hasFirstAccessState);
EXPECT_TRUE(transitionPlan.hasLastAccessState);
EXPECT_EQ(transitionPlan.initialState, ResourceStates::Common);
EXPECT_EQ(transitionPlan.firstAccessState, ResourceStates::DepthWrite);
EXPECT_EQ(transitionPlan.lastAccessState, ResourceStates::DepthWrite);
EXPECT_EQ(transitionPlan.finalState, ResourceStates::DepthWrite);
}
TEST(RenderGraph_Test, ExecutesCompiledPassCallbacksInCompiledOrder) {
RenderGraph graph;
RenderGraphBuilder builder(graph);