Formalize fullscreen render request contract
This commit is contained in:
@@ -109,6 +109,20 @@ inline bool HasValidColorTarget(const RenderSurface& surface) {
|
|||||||
surface.GetRenderAreaHeight() > 0;
|
surface.GetRenderAreaHeight() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool HasValidSurfaceSampleDescription(const RenderSurface& surface) {
|
||||||
|
const uint32_t sampleCount = surface.GetSampleCount();
|
||||||
|
const uint32_t sampleQuality = surface.GetSampleQuality();
|
||||||
|
return sampleCount > 0u &&
|
||||||
|
(sampleCount > 1u || sampleQuality == 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HasValidSingleSampleColorSource(const RenderSurface& surface) {
|
||||||
|
return HasValidColorTarget(surface) &&
|
||||||
|
HasValidSurfaceSampleDescription(surface) &&
|
||||||
|
surface.GetSampleCount() == 1u &&
|
||||||
|
surface.GetSampleQuality() == 0u;
|
||||||
|
}
|
||||||
|
|
||||||
struct DirectionalShadowRenderPlan {
|
struct DirectionalShadowRenderPlan {
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
Math::Vector3 lightDirection = Math::Vector3::Back();
|
Math::Vector3 lightDirection = Math::Vector3::Back();
|
||||||
@@ -149,6 +163,7 @@ struct ObjectIdRenderRequest {
|
|||||||
struct FullscreenPassRenderRequest {
|
struct FullscreenPassRenderRequest {
|
||||||
RenderSurface sourceSurface;
|
RenderSurface sourceSurface;
|
||||||
RHI::RHIResourceView* sourceColorView = nullptr;
|
RHI::RHIResourceView* sourceColorView = nullptr;
|
||||||
|
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
|
||||||
RenderSurface destinationSurface;
|
RenderSurface destinationSurface;
|
||||||
RenderPassSequence* passes = nullptr;
|
RenderPassSequence* passes = nullptr;
|
||||||
|
|
||||||
@@ -165,10 +180,15 @@ struct FullscreenPassRenderRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid() const {
|
bool IsValid() const {
|
||||||
|
const bool sourceStateIsUsable =
|
||||||
|
sourceSurface.IsAutoTransitionEnabled() ||
|
||||||
|
sourceColorState == RHI::ResourceStates::PixelShaderResource;
|
||||||
return passes != nullptr &&
|
return passes != nullptr &&
|
||||||
HasValidColorTarget(sourceSurface) &&
|
HasValidSingleSampleColorSource(sourceSurface) &&
|
||||||
sourceColorView != nullptr &&
|
sourceColorView != nullptr &&
|
||||||
HasValidColorTarget(destinationSurface);
|
sourceStateIsUsable &&
|
||||||
|
HasValidColorTarget(destinationSurface) &&
|
||||||
|
HasValidSurfaceSampleDescription(destinationSurface);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -322,6 +342,17 @@ struct CameraRenderRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RHI::ResourceStates GetSourceColorState(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.IsRequested() ? postProcess.sourceColorState : RHI::ResourceStates::Common;
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.IsRequested() ? finalOutput.sourceColorState : RHI::ResourceStates::Common;
|
||||||
|
default:
|
||||||
|
return RHI::ResourceStates::Common;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RequiresIntermediateSceneColor() const {
|
bool RequiresIntermediateSceneColor() const {
|
||||||
return postProcess.IsRequested() || finalOutput.IsRequested();
|
return postProcess.IsRequested() || finalOutput.IsRequested();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,6 +429,7 @@ public:
|
|||||||
lastSourceSurfaceHeight = context.sourceSurface->GetRenderAreaHeight();
|
lastSourceSurfaceHeight = context.sourceSurface->GetRenderAreaHeight();
|
||||||
}
|
}
|
||||||
lastSourceColorView = context.sourceColorView;
|
lastSourceColorView = context.sourceColorView;
|
||||||
|
lastSourceColorState = context.sourceColorState;
|
||||||
return m_executeResult;
|
return m_executeResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,6 +448,7 @@ public:
|
|||||||
uint32_t lastSourceSurfaceWidth = 0;
|
uint32_t lastSourceSurfaceWidth = 0;
|
||||||
uint32_t lastSourceSurfaceHeight = 0;
|
uint32_t lastSourceSurfaceHeight = 0;
|
||||||
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
|
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
|
||||||
|
XCEngine::RHI::ResourceStates lastSourceColorState = XCEngine::RHI::ResourceStates::Common;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<MockPipelineState> m_state;
|
std::shared_ptr<MockPipelineState> m_state;
|
||||||
@@ -487,6 +489,7 @@ public:
|
|||||||
lastSourceSurfaceHeight = context.sourceSurface->GetRenderAreaHeight();
|
lastSourceSurfaceHeight = context.sourceSurface->GetRenderAreaHeight();
|
||||||
}
|
}
|
||||||
lastSourceColorView = context.sourceColorView;
|
lastSourceColorView = context.sourceColorView;
|
||||||
|
lastSourceColorState = context.sourceColorState;
|
||||||
return m_executeResult;
|
return m_executeResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,6 +510,7 @@ public:
|
|||||||
uint32_t lastSourceSurfaceWidth = 0;
|
uint32_t lastSourceSurfaceWidth = 0;
|
||||||
uint32_t lastSourceSurfaceHeight = 0;
|
uint32_t lastSourceSurfaceHeight = 0;
|
||||||
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
|
XCEngine::RHI::RHIResourceView* lastSourceColorView = nullptr;
|
||||||
|
XCEngine::RHI::ResourceStates lastSourceColorState = XCEngine::RHI::ResourceStates::Common;
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderContext CreateValidContext() {
|
RenderContext CreateValidContext() {
|
||||||
@@ -545,12 +549,14 @@ TEST(CameraRenderRequest_Test, ReportsFormalFrameStageContract) {
|
|||||||
request.postProcess.sourceSurface = RenderSurface(256, 128);
|
request.postProcess.sourceSurface = RenderSurface(256, 128);
|
||||||
request.postProcess.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(2));
|
request.postProcess.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(2));
|
||||||
request.postProcess.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(20);
|
request.postProcess.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(20);
|
||||||
|
request.postProcess.sourceColorState = XCEngine::RHI::ResourceStates::PixelShaderResource;
|
||||||
request.postProcess.destinationSurface = RenderSurface(512, 256);
|
request.postProcess.destinationSurface = RenderSurface(512, 256);
|
||||||
request.postProcess.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(3));
|
request.postProcess.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(3));
|
||||||
|
|
||||||
request.finalOutput.sourceSurface = RenderSurface(512, 256);
|
request.finalOutput.sourceSurface = RenderSurface(512, 256);
|
||||||
request.finalOutput.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(4));
|
request.finalOutput.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(4));
|
||||||
request.finalOutput.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(40);
|
request.finalOutput.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(40);
|
||||||
|
request.finalOutput.sourceColorState = XCEngine::RHI::ResourceStates::PixelShaderResource;
|
||||||
request.finalOutput.destinationSurface = RenderSurface(640, 360);
|
request.finalOutput.destinationSurface = RenderSurface(640, 360);
|
||||||
request.finalOutput.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(5));
|
request.finalOutput.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(5));
|
||||||
|
|
||||||
@@ -605,11 +611,54 @@ TEST(CameraRenderRequest_Test, ReportsFormalFrameStageContract) {
|
|||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
request.GetSourceColorView(CameraFrameStage::PostProcess),
|
request.GetSourceColorView(CameraFrameStage::PostProcess),
|
||||||
reinterpret_cast<XCEngine::RHI::RHIResourceView*>(20));
|
reinterpret_cast<XCEngine::RHI::RHIResourceView*>(20));
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.GetSourceColorState(CameraFrameStage::PostProcess),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
ASSERT_NE(request.GetSourceSurface(CameraFrameStage::FinalOutput), nullptr);
|
ASSERT_NE(request.GetSourceSurface(CameraFrameStage::FinalOutput), nullptr);
|
||||||
EXPECT_EQ(request.GetSourceSurface(CameraFrameStage::FinalOutput)->GetRenderAreaWidth(), 512u);
|
EXPECT_EQ(request.GetSourceSurface(CameraFrameStage::FinalOutput)->GetRenderAreaWidth(), 512u);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
request.GetSourceColorView(CameraFrameStage::FinalOutput),
|
request.GetSourceColorView(CameraFrameStage::FinalOutput),
|
||||||
reinterpret_cast<XCEngine::RHI::RHIResourceView*>(40));
|
reinterpret_cast<XCEngine::RHI::RHIResourceView*>(40));
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.GetSourceColorState(CameraFrameStage::FinalOutput),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CameraRenderRequest_Test, RejectsFullscreenRequestWithoutReadableSourceStateWhenAutoTransitionIsDisabled) {
|
||||||
|
RenderPassSequence passes;
|
||||||
|
|
||||||
|
FullscreenPassRenderRequest request = {};
|
||||||
|
request.sourceSurface = RenderSurface(256, 128);
|
||||||
|
request.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(1));
|
||||||
|
request.sourceSurface.SetAutoTransitionEnabled(false);
|
||||||
|
request.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(2);
|
||||||
|
request.sourceColorState = XCEngine::RHI::ResourceStates::RenderTarget;
|
||||||
|
request.destinationSurface = RenderSurface(512, 256);
|
||||||
|
request.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(3));
|
||||||
|
request.passes = &passes;
|
||||||
|
|
||||||
|
EXPECT_FALSE(request.IsValid());
|
||||||
|
|
||||||
|
request.sourceColorState = XCEngine::RHI::ResourceStates::PixelShaderResource;
|
||||||
|
EXPECT_TRUE(request.IsValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CameraRenderRequest_Test, AcceptsAutoTransitionedFullscreenSourceAndRejectsMultisampledSource) {
|
||||||
|
RenderPassSequence passes;
|
||||||
|
|
||||||
|
FullscreenPassRenderRequest request = {};
|
||||||
|
request.sourceSurface = RenderSurface(256, 128);
|
||||||
|
request.sourceSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(1));
|
||||||
|
request.sourceColorView = reinterpret_cast<XCEngine::RHI::RHIResourceView*>(2);
|
||||||
|
request.sourceColorState = XCEngine::RHI::ResourceStates::RenderTarget;
|
||||||
|
request.destinationSurface = RenderSurface(512, 256);
|
||||||
|
request.destinationSurface.SetColorAttachment(reinterpret_cast<XCEngine::RHI::RHIResourceView*>(3));
|
||||||
|
request.passes = &passes;
|
||||||
|
|
||||||
|
EXPECT_TRUE(request.IsValid());
|
||||||
|
|
||||||
|
request.sourceSurface.SetSampleDesc(4u, 0u);
|
||||||
|
EXPECT_FALSE(request.IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CameraRenderer_Test, UsesOverrideCameraAndSurfaceSizeWhenSubmittingScene) {
|
TEST(CameraRenderer_Test, UsesOverrideCameraAndSurfaceSizeWhenSubmittingScene) {
|
||||||
@@ -1430,6 +1479,78 @@ TEST(CameraRenderer_Test, RecreatesDirectionalShadowSurfaceWhenPlanSizeChanges)
|
|||||||
EXPECT_EQ(allocationState->destroyTextureCalls, 2);
|
EXPECT_EQ(allocationState->destroyTextureCalls, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CameraRenderer_Test, EnablesDirectionalShadowSurfaceAfterInitialFrameWithoutShadows) {
|
||||||
|
Scene scene("CameraRendererDirectionalShadowToggleScene");
|
||||||
|
|
||||||
|
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||||
|
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||||
|
camera->SetPrimary(true);
|
||||||
|
camera->SetDepth(2.0f);
|
||||||
|
|
||||||
|
auto pipelineState = std::make_shared<MockPipelineState>();
|
||||||
|
auto allocationState = std::make_shared<MockShadowAllocationState>();
|
||||||
|
MockShadowDevice device(allocationState);
|
||||||
|
|
||||||
|
RenderContext context = CreateValidContext();
|
||||||
|
context.device = &device;
|
||||||
|
|
||||||
|
{
|
||||||
|
CameraRenderer renderer(
|
||||||
|
std::make_unique<MockPipeline>(pipelineState),
|
||||||
|
std::make_unique<MockObjectIdPass>(pipelineState));
|
||||||
|
|
||||||
|
auto shadowPass = std::make_unique<MockScenePass>(pipelineState, "shadowCaster");
|
||||||
|
renderer.SetShadowCasterPass(std::move(shadowPass));
|
||||||
|
|
||||||
|
CameraRenderRequest request;
|
||||||
|
request.scene = &scene;
|
||||||
|
request.camera = camera;
|
||||||
|
request.context = context;
|
||||||
|
request.surface = RenderSurface(320, 180);
|
||||||
|
request.cameraDepth = camera->GetDepth();
|
||||||
|
|
||||||
|
ASSERT_TRUE(renderer.Render(request));
|
||||||
|
EXPECT_EQ(pipelineState->eventLog, (std::vector<std::string>{ "pipeline" }));
|
||||||
|
EXPECT_FALSE(pipelineState->lastHasMainDirectionalShadow);
|
||||||
|
EXPECT_EQ(pipelineState->lastShadowMap, nullptr);
|
||||||
|
EXPECT_EQ(allocationState->createTextureCalls, 0);
|
||||||
|
EXPECT_EQ(allocationState->createDepthViewCalls, 0);
|
||||||
|
EXPECT_EQ(allocationState->createShaderViewCalls, 0);
|
||||||
|
|
||||||
|
pipelineState->eventLog.clear();
|
||||||
|
|
||||||
|
request.directionalShadow.enabled = true;
|
||||||
|
request.directionalShadow.mapWidth = 256;
|
||||||
|
request.directionalShadow.mapHeight = 128;
|
||||||
|
request.directionalShadow.cameraData.viewportWidth = 256;
|
||||||
|
request.directionalShadow.cameraData.viewportHeight = 128;
|
||||||
|
request.directionalShadow.cameraData.clearFlags = RenderClearFlags::Depth;
|
||||||
|
|
||||||
|
ASSERT_TRUE(renderer.Render(request));
|
||||||
|
EXPECT_EQ(
|
||||||
|
pipelineState->eventLog,
|
||||||
|
(std::vector<std::string>{
|
||||||
|
"init:shadowCaster",
|
||||||
|
"shadowCaster",
|
||||||
|
"pipeline" }));
|
||||||
|
EXPECT_TRUE(pipelineState->lastHasMainDirectionalShadow);
|
||||||
|
EXPECT_NE(pipelineState->lastShadowMap, nullptr);
|
||||||
|
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->createDepthViewCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->createShaderViewCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->shutdownDepthViewCalls, 0);
|
||||||
|
EXPECT_EQ(allocationState->shutdownShaderViewCalls, 0);
|
||||||
|
EXPECT_EQ(allocationState->shutdownTextureCalls, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(allocationState->shutdownDepthViewCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->shutdownShaderViewCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->shutdownTextureCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->destroyDepthViewCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->destroyShaderViewCalls, 1);
|
||||||
|
EXPECT_EQ(allocationState->destroyTextureCalls, 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CameraRenderer_Test, StopsRenderingWhenShadowCasterRequestIsInvalid) {
|
TEST(CameraRenderer_Test, StopsRenderingWhenShadowCasterRequestIsInvalid) {
|
||||||
Scene scene("CameraRendererInvalidShadowScene");
|
Scene scene("CameraRendererInvalidShadowScene");
|
||||||
|
|
||||||
@@ -1823,6 +1944,8 @@ TEST(SceneRenderer_Test, BuildsCameraColorScalePostProcessRequestFromCameraPassS
|
|||||||
RenderSurface surface(800, 600);
|
RenderSurface surface(800, 600);
|
||||||
surface.SetColorAttachment(backBufferColorView);
|
surface.SetColorAttachment(backBufferColorView);
|
||||||
surface.SetDepthAttachment(depthView);
|
surface.SetDepthAttachment(depthView);
|
||||||
|
surface.SetDepthStateBefore(XCEngine::RHI::ResourceStates::Common);
|
||||||
|
surface.SetDepthStateAfter(XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
|
|
||||||
SceneRenderer renderer;
|
SceneRenderer renderer;
|
||||||
const std::vector<CameraRenderRequest> requests =
|
const std::vector<CameraRenderRequest> requests =
|
||||||
@@ -1836,7 +1959,19 @@ TEST(SceneRenderer_Test, BuildsCameraColorScalePostProcessRequestFromCameraPassS
|
|||||||
ASSERT_EQ(request.postProcess.passes->GetPassCount(), 2u);
|
ASSERT_EQ(request.postProcess.passes->GetPassCount(), 2u);
|
||||||
EXPECT_EQ(request.postProcess.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
EXPECT_EQ(request.postProcess.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
||||||
EXPECT_EQ(request.postProcess.destinationSurface.GetDepthAttachment(), depthView);
|
EXPECT_EQ(request.postProcess.destinationSurface.GetDepthAttachment(), depthView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.destinationSurface.GetDepthStateBefore(),
|
||||||
|
XCEngine::RHI::ResourceStates::Common);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.destinationSurface.GetDepthStateAfter(),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
EXPECT_EQ(request.postProcess.sourceSurface.GetDepthAttachment(), depthView);
|
EXPECT_EQ(request.postProcess.sourceSurface.GetDepthAttachment(), depthView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.sourceSurface.GetDepthStateBefore(),
|
||||||
|
XCEngine::RHI::ResourceStates::Common);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.sourceSurface.GetDepthStateAfter(),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
EXPECT_EQ(request.postProcess.sourceSurface.GetWidth(), 800u);
|
EXPECT_EQ(request.postProcess.sourceSurface.GetWidth(), 800u);
|
||||||
EXPECT_EQ(request.postProcess.sourceSurface.GetHeight(), 600u);
|
EXPECT_EQ(request.postProcess.sourceSurface.GetHeight(), 600u);
|
||||||
const XCEngine::Math::RectInt sourceRenderArea = request.postProcess.sourceSurface.GetRenderArea();
|
const XCEngine::Math::RectInt sourceRenderArea = request.postProcess.sourceSurface.GetRenderArea();
|
||||||
@@ -1846,6 +1981,9 @@ TEST(SceneRenderer_Test, BuildsCameraColorScalePostProcessRequestFromCameraPassS
|
|||||||
EXPECT_EQ(sourceRenderArea.height, 375);
|
EXPECT_EQ(sourceRenderArea.height, 375);
|
||||||
EXPECT_NE(request.postProcess.sourceColorView, nullptr);
|
EXPECT_NE(request.postProcess.sourceColorView, nullptr);
|
||||||
EXPECT_NE(request.postProcess.sourceColorView, backBufferColorView);
|
EXPECT_NE(request.postProcess.sourceColorView, backBufferColorView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.sourceColorState,
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
ASSERT_FALSE(request.postProcess.sourceSurface.GetColorAttachments().empty());
|
ASSERT_FALSE(request.postProcess.sourceSurface.GetColorAttachments().empty());
|
||||||
EXPECT_NE(request.postProcess.sourceSurface.GetColorAttachments()[0], backBufferColorView);
|
EXPECT_NE(request.postProcess.sourceSurface.GetColorAttachments()[0], backBufferColorView);
|
||||||
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
||||||
@@ -1941,6 +2079,8 @@ TEST(SceneRenderer_Test, BuildsFinalOutputRequestFromResolvedFinalColorPolicy) {
|
|||||||
RenderSurface surface(800, 600);
|
RenderSurface surface(800, 600);
|
||||||
surface.SetColorAttachment(backBufferColorView);
|
surface.SetColorAttachment(backBufferColorView);
|
||||||
surface.SetDepthAttachment(depthView);
|
surface.SetDepthAttachment(depthView);
|
||||||
|
surface.SetDepthStateBefore(XCEngine::RHI::ResourceStates::Common);
|
||||||
|
surface.SetDepthStateAfter(XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
|
|
||||||
SceneRenderer renderer(std::make_shared<MockPipelineAsset>(assetState));
|
SceneRenderer renderer(std::make_shared<MockPipelineAsset>(assetState));
|
||||||
const std::vector<CameraRenderRequest> requests =
|
const std::vector<CameraRenderRequest> requests =
|
||||||
@@ -1955,11 +2095,26 @@ TEST(SceneRenderer_Test, BuildsFinalOutputRequestFromResolvedFinalColorPolicy) {
|
|||||||
EXPECT_EQ(request.finalOutput.passes->GetPassCount(), 1u);
|
EXPECT_EQ(request.finalOutput.passes->GetPassCount(), 1u);
|
||||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
EXPECT_EQ(request.finalOutput.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
||||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetDepthAttachment(), depthView);
|
EXPECT_EQ(request.finalOutput.destinationSurface.GetDepthAttachment(), depthView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.destinationSurface.GetDepthStateBefore(),
|
||||||
|
XCEngine::RHI::ResourceStates::Common);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.destinationSurface.GetDepthStateAfter(),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetDepthAttachment(), depthView);
|
EXPECT_EQ(request.finalOutput.sourceSurface.GetDepthAttachment(), depthView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.sourceSurface.GetDepthStateBefore(),
|
||||||
|
XCEngine::RHI::ResourceStates::Common);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.sourceSurface.GetDepthStateAfter(),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetWidth(), 800u);
|
EXPECT_EQ(request.finalOutput.sourceSurface.GetWidth(), 800u);
|
||||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetHeight(), 600u);
|
EXPECT_EQ(request.finalOutput.sourceSurface.GetHeight(), 600u);
|
||||||
EXPECT_NE(request.finalOutput.sourceColorView, nullptr);
|
EXPECT_NE(request.finalOutput.sourceColorView, nullptr);
|
||||||
EXPECT_NE(request.finalOutput.sourceColorView, backBufferColorView);
|
EXPECT_NE(request.finalOutput.sourceColorView, backBufferColorView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.sourceColorState,
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
ASSERT_FALSE(request.finalOutput.sourceSurface.GetColorAttachments().empty());
|
ASSERT_FALSE(request.finalOutput.sourceSurface.GetColorAttachments().empty());
|
||||||
EXPECT_NE(request.finalOutput.sourceSurface.GetColorAttachments()[0], backBufferColorView);
|
EXPECT_NE(request.finalOutput.sourceSurface.GetColorAttachments()[0], backBufferColorView);
|
||||||
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
||||||
@@ -2010,6 +2165,8 @@ TEST(SceneRenderer_Test, RoutesPostProcessIntoIntermediateSurfaceBeforeFinalOutp
|
|||||||
RenderSurface surface(800, 600);
|
RenderSurface surface(800, 600);
|
||||||
surface.SetColorAttachment(backBufferColorView);
|
surface.SetColorAttachment(backBufferColorView);
|
||||||
surface.SetDepthAttachment(depthView);
|
surface.SetDepthAttachment(depthView);
|
||||||
|
surface.SetDepthStateBefore(XCEngine::RHI::ResourceStates::Common);
|
||||||
|
surface.SetDepthStateAfter(XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
|
|
||||||
SceneRenderer renderer;
|
SceneRenderer renderer;
|
||||||
const std::vector<CameraRenderRequest> requests =
|
const std::vector<CameraRenderRequest> requests =
|
||||||
@@ -2037,9 +2194,21 @@ TEST(SceneRenderer_Test, RoutesPostProcessIntoIntermediateSurfaceBeforeFinalOutp
|
|||||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
EXPECT_EQ(request.finalOutput.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
||||||
|
|
||||||
EXPECT_EQ(request.postProcess.sourceSurface.GetDepthAttachment(), depthView);
|
EXPECT_EQ(request.postProcess.sourceSurface.GetDepthAttachment(), depthView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.sourceSurface.GetDepthStateBefore(),
|
||||||
|
XCEngine::RHI::ResourceStates::Common);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.sourceSurface.GetDepthStateAfter(),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
EXPECT_EQ(request.postProcess.destinationSurface.GetDepthAttachment(), nullptr);
|
EXPECT_EQ(request.postProcess.destinationSurface.GetDepthAttachment(), nullptr);
|
||||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetDepthAttachment(), nullptr);
|
EXPECT_EQ(request.finalOutput.sourceSurface.GetDepthAttachment(), nullptr);
|
||||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetDepthAttachment(), depthView);
|
EXPECT_EQ(request.finalOutput.destinationSurface.GetDepthAttachment(), depthView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.destinationSurface.GetDepthStateBefore(),
|
||||||
|
XCEngine::RHI::ResourceStates::Common);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.destinationSurface.GetDepthStateAfter(),
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
|
|
||||||
const XCEngine::Math::RectInt postProcessSourceArea = request.postProcess.sourceSurface.GetRenderArea();
|
const XCEngine::Math::RectInt postProcessSourceArea = request.postProcess.sourceSurface.GetRenderArea();
|
||||||
EXPECT_EQ(postProcessSourceArea.x, 200);
|
EXPECT_EQ(postProcessSourceArea.x, 200);
|
||||||
@@ -2055,6 +2224,12 @@ TEST(SceneRenderer_Test, RoutesPostProcessIntoIntermediateSurfaceBeforeFinalOutp
|
|||||||
EXPECT_NE(request.postProcess.sourceColorView, nullptr);
|
EXPECT_NE(request.postProcess.sourceColorView, nullptr);
|
||||||
EXPECT_NE(request.finalOutput.sourceColorView, nullptr);
|
EXPECT_NE(request.finalOutput.sourceColorView, nullptr);
|
||||||
EXPECT_NE(request.postProcess.sourceColorView, request.finalOutput.sourceColorView);
|
EXPECT_NE(request.postProcess.sourceColorView, request.finalOutput.sourceColorView);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.postProcess.sourceColorState,
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
|
EXPECT_EQ(
|
||||||
|
request.finalOutput.sourceColorState,
|
||||||
|
XCEngine::RHI::ResourceStates::PixelShaderResource);
|
||||||
EXPECT_EQ(allocationState->createTextureCalls, 2);
|
EXPECT_EQ(allocationState->createTextureCalls, 2);
|
||||||
EXPECT_EQ(allocationState->createRenderTargetViewCalls, 2);
|
EXPECT_EQ(allocationState->createRenderTargetViewCalls, 2);
|
||||||
EXPECT_EQ(allocationState->createShaderViewCalls, 2);
|
EXPECT_EQ(allocationState->createShaderViewCalls, 2);
|
||||||
@@ -2063,6 +2238,62 @@ TEST(SceneRenderer_Test, RoutesPostProcessIntoIntermediateSurfaceBeforeFinalOutp
|
|||||||
delete backBufferColorView;
|
delete backBufferColorView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SceneRenderer_Test, DoesNotBuildFullscreenStagesForMultisampledMainSceneSurface) {
|
||||||
|
Scene scene("SceneRendererMultisampledFullscreenStageScene");
|
||||||
|
|
||||||
|
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||||
|
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||||
|
camera->SetPrimary(true);
|
||||||
|
camera->SetDepth(2.0f);
|
||||||
|
camera->SetPostProcessPasses({
|
||||||
|
XCEngine::Rendering::CameraPostProcessPassDesc::MakeColorScale(
|
||||||
|
XCEngine::Math::Vector4(1.0f, 0.75f, 0.75f, 1.0f))
|
||||||
|
});
|
||||||
|
|
||||||
|
FinalColorOverrideSettings cameraOverrides = {};
|
||||||
|
cameraOverrides.overrideOutputTransferMode = true;
|
||||||
|
cameraOverrides.outputTransferMode = FinalColorOutputTransferMode::LinearToSRGB;
|
||||||
|
camera->SetFinalColorOverrides(cameraOverrides);
|
||||||
|
|
||||||
|
auto allocationState = std::make_shared<MockShadowAllocationState>();
|
||||||
|
MockShadowDevice device(allocationState);
|
||||||
|
|
||||||
|
auto* backBufferColorView = new MockShadowView(
|
||||||
|
allocationState,
|
||||||
|
XCEngine::RHI::ResourceViewType::RenderTarget,
|
||||||
|
XCEngine::RHI::Format::R8G8B8A8_UNorm,
|
||||||
|
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||||
|
auto* depthView = new MockShadowView(
|
||||||
|
allocationState,
|
||||||
|
XCEngine::RHI::ResourceViewType::DepthStencil,
|
||||||
|
XCEngine::RHI::Format::D24_UNorm_S8_UInt,
|
||||||
|
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||||
|
|
||||||
|
RenderContext context = CreateValidContext();
|
||||||
|
context.device = &device;
|
||||||
|
|
||||||
|
RenderSurface surface(800, 600);
|
||||||
|
surface.SetColorAttachment(backBufferColorView);
|
||||||
|
surface.SetDepthAttachment(depthView);
|
||||||
|
surface.SetSampleDesc(4u, 0u);
|
||||||
|
|
||||||
|
SceneRenderer renderer;
|
||||||
|
const std::vector<CameraRenderRequest> requests =
|
||||||
|
renderer.BuildRenderRequests(scene, nullptr, context, surface);
|
||||||
|
|
||||||
|
ASSERT_EQ(requests.size(), 1u);
|
||||||
|
const CameraRenderRequest& request = requests[0];
|
||||||
|
EXPECT_EQ(request.surface.GetSampleCount(), 4u);
|
||||||
|
EXPECT_FALSE(request.postProcess.IsRequested());
|
||||||
|
EXPECT_FALSE(request.finalOutput.IsRequested());
|
||||||
|
EXPECT_EQ(allocationState->createTextureCalls, 0);
|
||||||
|
EXPECT_EQ(allocationState->createRenderTargetViewCalls, 0);
|
||||||
|
EXPECT_EQ(allocationState->createShaderViewCalls, 0);
|
||||||
|
|
||||||
|
delete depthView;
|
||||||
|
delete backBufferColorView;
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SceneRenderer_Test, ReusesTrackedSceneColorStateAcrossFramesWhenPostProcessIsEnabled) {
|
TEST(SceneRenderer_Test, ReusesTrackedSceneColorStateAcrossFramesWhenPostProcessIsEnabled) {
|
||||||
Scene scene("SceneRendererTrackedSceneColorStateScene");
|
Scene scene("SceneRendererTrackedSceneColorStateScene");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user