Add render graph runtime UAV support
This commit is contained in:
@@ -28,6 +28,9 @@ struct MockTransientAllocationState {
|
||||
int createShaderViewCalls = 0;
|
||||
int shutdownShaderViewCalls = 0;
|
||||
int destroyShaderViewCalls = 0;
|
||||
int createUnorderedAccessViewCalls = 0;
|
||||
int shutdownUnorderedAccessViewCalls = 0;
|
||||
int destroyUnorderedAccessViewCalls = 0;
|
||||
};
|
||||
|
||||
class MockTransientTexture final : public RHITexture {
|
||||
@@ -88,6 +91,8 @@ public:
|
||||
++m_state->destroyRenderTargetViewCalls;
|
||||
} else if (m_viewType == ResourceViewType::DepthStencil) {
|
||||
++m_state->destroyDepthViewCalls;
|
||||
} else if (m_viewType == ResourceViewType::UnorderedAccess) {
|
||||
++m_state->destroyUnorderedAccessViewCalls;
|
||||
} else {
|
||||
++m_state->destroyShaderViewCalls;
|
||||
}
|
||||
@@ -98,6 +103,8 @@ public:
|
||||
++m_state->shutdownRenderTargetViewCalls;
|
||||
} else if (m_viewType == ResourceViewType::DepthStencil) {
|
||||
++m_state->shutdownDepthViewCalls;
|
||||
} else if (m_viewType == ResourceViewType::UnorderedAccess) {
|
||||
++m_state->shutdownUnorderedAccessViewCalls;
|
||||
} else {
|
||||
++m_state->shutdownShaderViewCalls;
|
||||
}
|
||||
@@ -223,8 +230,14 @@ public:
|
||||
}
|
||||
|
||||
RHIResourceView* CreateUnorderedAccessView(RHIBuffer*, const ResourceViewDesc&) override { return nullptr; }
|
||||
RHIResourceView* CreateUnorderedAccessView(RHITexture*, const ResourceViewDesc&) override {
|
||||
return nullptr;
|
||||
RHIResourceView* CreateUnorderedAccessView(
|
||||
RHITexture*,
|
||||
const ResourceViewDesc& desc) override {
|
||||
++m_state->createUnorderedAccessViewCalls;
|
||||
return new MockTransientView(
|
||||
m_state,
|
||||
ResourceViewType::UnorderedAccess,
|
||||
static_cast<Format>(desc.format));
|
||||
}
|
||||
|
||||
const RHICapabilities& GetCapabilities() const override { return m_capabilities; }
|
||||
@@ -721,6 +734,130 @@ TEST(RenderGraph_Test, ExecutesGraphOwnedImportedDepthTransitionsAtGraphBoundari
|
||||
EXPECT_EQ(commandList.transitionCalls[1].after, ResourceStates::DepthWrite);
|
||||
}
|
||||
|
||||
TEST(RenderGraph_Test, ExecutesTransientComputeTransitionsWithUnorderedAccessView) {
|
||||
RenderGraph graph;
|
||||
RenderGraphBuilder builder(graph);
|
||||
|
||||
const RenderGraphTextureDesc desc = BuildTestTextureDesc();
|
||||
const RenderGraphTextureHandle sceneColor = builder.CreateTransientTexture("SceneColor", desc);
|
||||
|
||||
RHIResourceView* computeWriteView = nullptr;
|
||||
RHIResourceView* computeReadView = nullptr;
|
||||
builder.AddComputePass(
|
||||
"Generate",
|
||||
[&](RenderGraphPassBuilder& pass) {
|
||||
pass.WriteTexture(sceneColor);
|
||||
pass.SetExecuteCallback(
|
||||
[&](const RenderGraphExecutionContext& executionContext) {
|
||||
computeWriteView =
|
||||
executionContext.ResolveTextureView(
|
||||
sceneColor,
|
||||
RenderGraphTextureViewType::UnorderedAccess);
|
||||
EXPECT_NE(computeWriteView, nullptr);
|
||||
});
|
||||
});
|
||||
|
||||
builder.AddComputePass(
|
||||
"Consume",
|
||||
[&](RenderGraphPassBuilder& pass) {
|
||||
pass.ReadTexture(sceneColor);
|
||||
pass.SetExecuteCallback(
|
||||
[&](const RenderGraphExecutionContext& executionContext) {
|
||||
computeReadView =
|
||||
executionContext.ResolveTextureView(
|
||||
sceneColor,
|
||||
RenderGraphTextureViewType::ShaderResource);
|
||||
EXPECT_NE(computeReadView, nullptr);
|
||||
EXPECT_NE(computeReadView, computeWriteView);
|
||||
});
|
||||
});
|
||||
|
||||
CompiledRenderGraph compiledGraph;
|
||||
XCEngine::Containers::String errorMessage;
|
||||
ASSERT_TRUE(RenderGraphCompiler::Compile(graph, compiledGraph, &errorMessage))
|
||||
<< errorMessage.CStr();
|
||||
|
||||
auto allocationState = std::make_shared<MockTransientAllocationState>();
|
||||
MockTransientDevice device(allocationState);
|
||||
MockTransientCommandList commandList;
|
||||
RenderContext renderContext = {};
|
||||
renderContext.device = &device;
|
||||
renderContext.commandList = &commandList;
|
||||
renderContext.commandQueue = reinterpret_cast<RHICommandQueue*>(1);
|
||||
ASSERT_TRUE(RenderGraphExecutor::Execute(compiledGraph, renderContext, &errorMessage))
|
||||
<< errorMessage.CStr();
|
||||
|
||||
ASSERT_EQ(commandList.transitionCalls.size(), 2u);
|
||||
EXPECT_EQ(commandList.transitionCalls[0].resource, computeWriteView);
|
||||
EXPECT_EQ(commandList.transitionCalls[0].before, ResourceStates::Common);
|
||||
EXPECT_EQ(commandList.transitionCalls[0].after, ResourceStates::UnorderedAccess);
|
||||
EXPECT_EQ(commandList.transitionCalls[1].resource, computeReadView);
|
||||
EXPECT_EQ(commandList.transitionCalls[1].before, ResourceStates::UnorderedAccess);
|
||||
EXPECT_EQ(commandList.transitionCalls[1].after, ResourceStates::GenericRead);
|
||||
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
||||
EXPECT_EQ(allocationState->createRenderTargetViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->createDepthViewCalls, 0);
|
||||
EXPECT_EQ(allocationState->createShaderViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->createUnorderedAccessViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->shutdownTextureCalls, 1);
|
||||
EXPECT_EQ(allocationState->shutdownRenderTargetViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->shutdownDepthViewCalls, 0);
|
||||
EXPECT_EQ(allocationState->shutdownShaderViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->shutdownUnorderedAccessViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->destroyTextureCalls, 1);
|
||||
EXPECT_EQ(allocationState->destroyRenderTargetViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->destroyDepthViewCalls, 0);
|
||||
EXPECT_EQ(allocationState->destroyShaderViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->destroyUnorderedAccessViewCalls, 1);
|
||||
}
|
||||
|
||||
TEST(RenderGraph_Test, ExecutesGraphOwnedImportedUnorderedAccessTransitionsAtGraphBoundaries) {
|
||||
RenderGraph graph;
|
||||
RenderGraphBuilder builder(graph);
|
||||
|
||||
const RenderGraphTextureDesc desc = BuildTestTextureDesc();
|
||||
RenderGraphImportedTextureOptions importedOptions = {};
|
||||
importedOptions.initialState = ResourceStates::GenericRead;
|
||||
importedOptions.finalState = ResourceStates::GenericRead;
|
||||
importedOptions.graphOwnsTransitions = true;
|
||||
|
||||
MockImportedView importedView(
|
||||
ResourceViewType::UnorderedAccess,
|
||||
Format::R8G8B8A8_UNorm);
|
||||
const RenderGraphTextureHandle importedTexture = builder.ImportTexture(
|
||||
"ImportedComputeTarget",
|
||||
desc,
|
||||
&importedView,
|
||||
importedOptions);
|
||||
|
||||
builder.AddComputePass(
|
||||
"WriteImported",
|
||||
[&](RenderGraphPassBuilder& pass) {
|
||||
pass.WriteTexture(importedTexture);
|
||||
});
|
||||
|
||||
CompiledRenderGraph compiledGraph;
|
||||
XCEngine::Containers::String errorMessage;
|
||||
ASSERT_TRUE(RenderGraphCompiler::Compile(graph, compiledGraph, &errorMessage))
|
||||
<< errorMessage.CStr();
|
||||
|
||||
MockTransientCommandList commandList;
|
||||
RenderContext renderContext = {};
|
||||
renderContext.device = reinterpret_cast<RHIDevice*>(1);
|
||||
renderContext.commandList = &commandList;
|
||||
renderContext.commandQueue = reinterpret_cast<RHICommandQueue*>(1);
|
||||
ASSERT_TRUE(RenderGraphExecutor::Execute(compiledGraph, renderContext, &errorMessage))
|
||||
<< errorMessage.CStr();
|
||||
|
||||
ASSERT_EQ(commandList.transitionCalls.size(), 2u);
|
||||
EXPECT_EQ(commandList.transitionCalls[0].resource, &importedView);
|
||||
EXPECT_EQ(commandList.transitionCalls[0].before, ResourceStates::GenericRead);
|
||||
EXPECT_EQ(commandList.transitionCalls[0].after, ResourceStates::UnorderedAccess);
|
||||
EXPECT_EQ(commandList.transitionCalls[1].resource, &importedView);
|
||||
EXPECT_EQ(commandList.transitionCalls[1].before, ResourceStates::UnorderedAccess);
|
||||
EXPECT_EQ(commandList.transitionCalls[1].after, ResourceStates::GenericRead);
|
||||
}
|
||||
|
||||
TEST(RenderGraph_Test, ExecutesCompiledPassCallbacksInCompiledOrder) {
|
||||
RenderGraph graph;
|
||||
RenderGraphBuilder builder(graph);
|
||||
|
||||
Reference in New Issue
Block a user