Skip to content

Commit

Permalink
Refactor pipeline (#17382)
Browse files Browse the repository at this point in the history
  • Loading branch information
star-e authored Jul 18, 2024
1 parent ccc5d49 commit 2c8aac1
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 42 deletions.
4 changes: 3 additions & 1 deletion cocos/rendering/custom/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { PipelineSceneData } from '../pipeline-scene-data';
import { PointLight } from '../../render-scene/scene/point-light';
import { RangedDirectionalLight } from '../../render-scene/scene/ranged-directional-light';
import { AccessType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency, UploadPair } from './types';
import { RenderScene } from '../../render-scene/core/render-scene';
import { RenderWindow } from '../../render-scene/core/render-window';
import { Light, Model } from '../../render-scene/scene';
import { SphereLight } from '../../render-scene/scene/sphere-light';
Expand Down Expand Up @@ -526,7 +527,8 @@ export interface RenderQueueBuilder extends Setter {
addScene (
camera: Camera,
sceneFlags: SceneFlags,
light?: Light): SceneBuilder;
light?: Light,
scene?: RenderScene): SceneBuilder;
/**
* @en Render a full-screen quad.
* @zh 渲染全屏四边形
Expand Down
129 changes: 98 additions & 31 deletions editor/assets/default_renderpipeline/builtin-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
THE SOFTWARE.
*/

import { DEBUG } from 'cc/env';
import { DEBUG, EDITOR } from 'cc/env';
import {
assert,
clamp,
Expand All @@ -40,6 +40,7 @@ import {
cclegacy,
PipelineEventType,
PipelineEventProcessor,
ReflectionProbeManager,
} from 'cc';

import {
Expand Down Expand Up @@ -151,6 +152,7 @@ class CameraConfigs {
enableHDR = false;
useFullPipeline = false;
singleForwardRadiancePass = false;
radianceFormat = gfx.Format.RGBA8;
shadingScale = 0.5;
settings: PipelineSettings = defaultSettings;
}
Expand Down Expand Up @@ -240,6 +242,9 @@ function setupCameraConfigs(

cameraConfigs.enableHDR = cameraConfigs.useFullPipeline
&& pipelineConfigs.useFloatOutput;

cameraConfigs.radianceFormat = cameraConfigs.enableHDR
? gfx.Format.RGBA16F : gfx.Format.RGBA8;
}

if (rendering) {
Expand Down Expand Up @@ -492,28 +497,27 @@ if (rendering) {
// Render Window (UI)
ppl.addRenderWindow(window.colorName, Format.RGBA8, nativeWidth, nativeHeight, window);

if (this._cameraConfigs.enableFSR) {
ppl.addRenderTarget(`FsrColor${id}`, Format.RGBA8, nativeWidth, nativeHeight);
if (this._cameraConfigs.enableShadingScale) {
ppl.addDepthStencil(`ScaledDepthStencil${id}`, Format.DEPTH_STENCIL, width, height);
ppl.addRenderTarget(`ScaledRadiance${id}`, this._cameraConfigs.radianceFormat, width, height);
ppl.addRenderTarget(`ScaledLdrColor${id}`, Format.RGBA8, width, height);
} else {
ppl.addDepthStencil(window.depthStencilName, Format.DEPTH_STENCIL, width, height);
ppl.addRenderTarget(`Radiance${id}`, this._cameraConfigs.radianceFormat, width, height);
ppl.addRenderTarget(`LdrColor${id}`, Format.RGBA8, width, height);
}

// Radiance
if (this._configs.useFloatOutput) {
ppl.addRenderTarget(`Radiance${id}`, Format.RGBA16F, width, height);
} else if (this._cameraConfigs.enableShadingScale || this._cameraConfigs.enablePostProcess) {
ppl.addRenderTarget(`Radiance${id}`, Format.RGBA8, width, height);
} else {
// Reuse render window
if (this._cameraConfigs.enableFSR) {
ppl.addRenderTarget(`FsrColor${id}`, Format.RGBA8, nativeWidth, nativeHeight);
}
ppl.addDepthStencil(window.depthStencilName, Format.DEPTH_STENCIL, width, height);
ppl.addRenderTarget(`LdrColor${id}`, Format.RGBA8, width, height);

// MsaaRadiance
if (this._cameraConfigs.enableMSAA) {
// Notice: We never store multisample results.
// These samples are always resolved and discarded at the end of the render pass.
// So the ResourceResidency should be MEMORYLESS.
if (this._cameraConfigs.enableHDR) {
ppl.addTexture(`MsaaRadiance${id}`, TextureType.TEX2D, Format.RGBA16F, width, height, 1, 1, 1,
ppl.addTexture(`MsaaRadiance${id}`, TextureType.TEX2D, this._cameraConfigs.radianceFormat, width, height, 1, 1, 1,
settings.msaa.sampleCount, ResourceFlags.COLOR_ATTACHMENT, ResourceResidency.MEMORYLESS);
} else {
ppl.addTexture(`MsaaRadiance${id}`, TextureType.TEX2D, Format.RGBA8, width, height, 1, 1, 1,
Expand Down Expand Up @@ -563,11 +567,11 @@ if (rendering) {
if (this._cameraConfigs.enableDOF) {
const halfWidth = Math.max(Math.floor(width / 2), 1);
const halfHeight = Math.max(Math.floor(height / 2), 1);
// `DofCoc${id}` texture will reuse `LdrColor${id}`
ppl.addRenderTarget(`DofRadiance${id}`, Format.RGBA16F, width, height);
ppl.addRenderTarget(`DofPrefilter${id}`, Format.RGBA16F, halfWidth, halfHeight);
ppl.addRenderTarget(`DofBokeh${id}`, Format.RGBA16F, halfWidth, halfHeight);
ppl.addRenderTarget(`DofFilter${id}`, Format.RGBA16F, halfWidth, halfHeight);
// `DofCoc${id}` texture will reuse ldrColorName
ppl.addRenderTarget(`DofRadiance${id}`, this._cameraConfigs.radianceFormat, width, height);
ppl.addRenderTarget(`DofPrefilter${id}`, this._cameraConfigs.radianceFormat, halfWidth, halfHeight);
ppl.addRenderTarget(`DofBokeh${id}`, this._cameraConfigs.radianceFormat, halfWidth, halfHeight);
ppl.addRenderTarget(`DofFilter${id}`, this._cameraConfigs.radianceFormat, halfWidth, halfHeight);
}
// Bloom (Kawase Dual Filter)
if (this._cameraConfigs.enableBloom) {
Expand All @@ -576,7 +580,7 @@ if (rendering) {
for (let i = 0; i !== settings.bloom.iterations + 1; ++i) {
bloomWidth = Math.max(Math.floor(bloomWidth / 2), 1);
bloomHeight = Math.max(Math.floor(bloomHeight / 2), 1);
ppl.addRenderTarget(`BloomTex${id}_${i}`, Format.RGBA16F, bloomWidth, bloomHeight);
ppl.addRenderTarget(`BloomTex${id}_${i}`, this._cameraConfigs.radianceFormat, bloomWidth, bloomHeight);
}
}
// Color Grading
Expand Down Expand Up @@ -686,8 +690,15 @@ if (rendering) {
: nativeHeight;
const id = camera.window.renderWindowId;
const colorName = camera.window.colorName;
const depthStencilName = camera.window.depthStencilName;
const radianceName = `Radiance${id}`;
const depthStencilName = this._cameraConfigs.enableShadingScale
? `ScaledDepthStencil${id}`
: camera.window.depthStencilName;
const radianceName = this._cameraConfigs.enableShadingScale
? `ScaledRadiance${id}`
: `Radiance${id}`;
const ldrColorName = this._cameraConfigs.enableShadingScale
? `ScaledLdrColor${id}`
: `LdrColor${id}`;
const mainLight = scene.mainLight;

// Forward Lighting (Light Culling)
Expand All @@ -706,6 +717,8 @@ if (rendering) {
this.forwardLighting.addSpotlightShadowPasses(ppl, camera, this._configs.mobileMaxSpotLightShadowMaps);
}

// this._tryAddReflectionProbePasses(ppl, id, mainLight, camera.scene);

// Forward Lighting
let lastPass: rendering.BasicRenderPassBuilder;
if (this._cameraConfigs.enablePostProcess) { // Post Process
Expand All @@ -718,7 +731,7 @@ if (rendering) {
dofRadianceName, depthStencilName, true, StoreOp.STORE);
this._addDepthOfFieldPasses(ppl, settings, settings.depthOfField.material,
id, camera, width, height,
dofRadianceName, depthStencilName, radianceName);
dofRadianceName, depthStencilName, radianceName, ldrColorName);
} else {
this._addForwardRadiancePasses(
ppl, id, camera, width, height, mainLight,
Expand All @@ -736,17 +749,17 @@ if (rendering) {
assert(!!settings.fxaa.material);
const copyAndTonemapPassNeeded = this._cameraConfigs.enableHDR
|| this._cameraConfigs.enableColorGrading;
const ldrColorName = copyAndTonemapPassNeeded ? `LdrColor${id}` : radianceName;
const ldrColorBufferName = copyAndTonemapPassNeeded ? ldrColorName : radianceName;
// FXAA is applied after tone mapping
if (copyAndTonemapPassNeeded) {
this._addCopyAndTonemapPass(ppl, settings, width, height, radianceName, ldrColorName);
this._addCopyAndTonemapPass(ppl, settings, width, height, radianceName, ldrColorBufferName);
}
// Apply FXAA
if (this._cameraConfigs.enableShadingScale) {
const aaColorName = `AaColor${id}`;
// Apply FXAA on scaled image
this._addFxaaPass(ppl, settings.fxaa.material,
width, height, ldrColorName, aaColorName);
width, height, ldrColorBufferName, aaColorName);
// Copy FXAA result to screen
if (this._cameraConfigs.enableFSR && settings.fsr.material) {
// Apply FSR
Expand All @@ -761,19 +774,19 @@ if (rendering) {
} else {
// Image not scaled, output FXAA result to screen directly
lastPass = this._addFxaaPass(ppl, settings.fxaa.material,
nativeWidth, nativeHeight, ldrColorName, colorName);
nativeWidth, nativeHeight, ldrColorBufferName, colorName);
}
} else {
// No FXAA (Size might be scaled)
lastPass = this._addTonemapResizeOrSuperResolutionPasses(ppl, settings, id,
width, height, radianceName,
width, height, radianceName, ldrColorName,
nativeWidth, nativeHeight, colorName);
}
} else if (this._cameraConfigs.enableHDR || this._cameraConfigs.enableShadingScale) { // HDR or Scaled LDR
this._addForwardRadiancePasses(ppl, id, camera,
width, height, mainLight, radianceName, depthStencilName);
lastPass = this._addTonemapResizeOrSuperResolutionPasses(ppl, settings, id,
width, height, radianceName,
width, height, radianceName, ldrColorName,
nativeWidth, nativeHeight, colorName);
} else { // LDR (Size is not scaled)
lastPass = this._addForwardRadiancePasses(ppl, id, camera,
Expand All @@ -794,11 +807,11 @@ if (rendering) {
width: number,
height: number,
radianceName: string,
ldrColorName: string,
nativeWidth: number,
nativeHeight: number,
colorName: string,
): rendering.BasicRenderPassBuilder {
const ldrColorName = `LdrColor${id}`;
let lastPass: rendering.BasicRenderPassBuilder;
if (this._cameraConfigs.enableFSR && settings.fsr.material) {
// Apply FSR
Expand Down Expand Up @@ -923,6 +936,7 @@ if (rendering) {
depthStencilName: string,
depthStencilStoreOp: gfx.StoreOp,
mainLight: renderer.scene.DirectionalLight | null,
scene: renderer.RenderScene | null = null,
): void {
// set viewport
pass.setViewport(this._viewport);
Expand Down Expand Up @@ -959,7 +973,10 @@ if (rendering) {

// add opaque and mask queue
pass.addQueue(QueueHint.NONE) // Currently we put OPAQUE and MASK into one queue, so QueueHint is NONE
.addScene(camera, SceneFlags.OPAQUE | SceneFlags.MASK, mainLight || undefined);
.addScene(camera,
SceneFlags.OPAQUE | SceneFlags.MASK,
mainLight || undefined,
scene ? scene : undefined);
}

private _addDepthOfFieldPasses(
Expand All @@ -973,6 +990,7 @@ if (rendering) {
dofRadianceName: string,
depthStencil: string,
radianceName: string,
ldrColorName: string,
): void {
// https://catlikecoding.com/unity/tutorials/advanced-rendering/depth-of-field/

Expand All @@ -988,7 +1006,7 @@ if (rendering) {
const halfWidth = Math.max(Math.floor(width / 2), 1);
const halfHeight = Math.max(Math.floor(height / 2), 1);

const cocName = `LdrColor${id}`;
const cocName = ldrColorName;
const prefilterName = `DofPrefilter${id}`;
const bokehName = `DofBokeh${id}`;
const filterName = `DofFilter${id}`;
Expand Down Expand Up @@ -1368,6 +1386,55 @@ if (rendering) {
return pass;
}

private _tryAddReflectionProbePasses(ppl: rendering.BasicPipeline, id: number,
mainLight: renderer.scene.DirectionalLight | null,
scene: renderer.RenderScene | null,
): void {
const reflectionProbeManager = cclegacy.internal.reflectionProbeManager as ReflectionProbeManager;
const probes = reflectionProbeManager.getProbes();
const maxProbeCount = 4;
let probeID = 0;
for (const probe of probes) {
if (!probe.needRender) {
continue;
}
const area = probe.renderArea();
const width = Math.max(Math.floor(area.x), 1);
const height = Math.max(Math.floor(area.y), 1);

if (probe.probeType === renderer.scene.ProbeType.PLANAR) {
const window: renderer.RenderWindow = probe.realtimePlanarTexture!.window!;
const colorName = `PlanarProbeRT${probeID}`;
const depthStencilName = `PlanarProbeDS${probeID}`;
// ProbeResource
ppl.addRenderWindow(colorName,
this._cameraConfigs.radianceFormat, width, height, window);
ppl.addDepthStencil(depthStencilName,
gfx.Format.DEPTH_STENCIL, width, height, ResourceResidency.MEMORYLESS);

// Rendering
const probePass = ppl.addRenderPass(width, height, 'default');
probePass.name = `PlanarProbe${probeID}`;
this._viewport.left = 0;
this._viewport.top = 0;
this._viewport.width = width;
this._viewport.height = height;
this._buildForwardMainLightPass(probePass, id, probe.camera,
colorName, depthStencilName, StoreOp.DISCARD, mainLight, scene);
} else if (EDITOR) {
// for (let faceIdx = 0; faceIdx < probe.bakedCubeTextures.length; faceIdx++) {
// probe.updateCameraDir(faceIdx);
// buildReflectionProbeRes(ppl, probe, probe.bakedCubeTextures[faceIdx].window!, faceIdx);
// }
probe.needRender = false;
}
++probeID;
if (probeID === maxProbeCount) {
break;
}
}
}

private _initMaterials(ppl: rendering.BasicPipeline): number {
if (this._initialized) {
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS
}

void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) override;
SceneBuilder *addScene(const scene::Camera *camera, SceneFlags sceneFlags, scene::Light *light) override;
SceneBuilder *addScene(const scene::Camera *camera, SceneFlags sceneFlags, scene::Light *light, scene::RenderScene *scene) override;
void addFullscreenQuad(Material *material, uint32_t passID, SceneFlags sceneFlags) override;
void addCameraQuad(scene::Camera *camera, Material *material, uint32_t passID, SceneFlags sceneFlags) override;
void clearRenderTarget(const ccstd::string &name, const gfx::Color &color) override;
Expand Down
18 changes: 13 additions & 5 deletions native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,16 +808,17 @@ void NativeSceneBuilder::useLightFrustum(
}

SceneBuilder *NativeRenderQueueBuilder::addScene(
const scene::Camera *camera, SceneFlags sceneFlags, scene::Light *light) {
const scene::Camera *camera, SceneFlags sceneFlags,
scene::Light *light, scene::RenderScene *scene) {
const auto sceneID = addVertex2(
SceneTag{},
std::forward_as_tuple("Scene"),
std::forward_as_tuple(),
std::forward_as_tuple(),
std::forward_as_tuple(),
std::forward_as_tuple(
camera->getScene(), // Scene and camera should be decoupled.
camera, // They are coupled for now.
scene ? scene : camera->getScene(), // Scene and camera should be decoupled.
camera, // They are coupled for now.
sceneFlags,
LightInfo{nullptr, 0},
// Objects are projected to camera by default and are culled further if light is available.
Expand All @@ -836,7 +837,15 @@ SceneBuilder *NativeRenderQueueBuilder::addScene(

if (!any(sceneFlags & SceneFlags::NON_BUILTIN)) {
// objects are projected to camera, set camera ubo
builder->setBuiltinCameraConstants(camera);
auto &data = get(RenderGraph::DataTag{}, *renderGraph, sceneID);
setCameraUBOValues(
*camera,
*layoutGraph,
*pipelineRuntime->getPipelineSceneData(),
scene ? scene->getMainLight()
: (camera->getScene() ? camera->getScene()->getMainLight()
: nullptr),
data);

if (light) {
switch (light->getType()) {
Expand All @@ -863,7 +872,6 @@ SceneBuilder *NativeRenderQueueBuilder::addScene(
}

// set builtin legacy ubo
auto &data = get(RenderGraph::DataTag{}, *renderGraph, sceneID);
setLegacyTextureUBOView(
*pipelineRuntime->getDevice(),
*layoutGraph,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ void SceneCulling::batchFrustumCulling(const NativePipeline& ppl) {
CC_ENSURES(scene);
for (const auto& [key, frustomCulledResultID] : queries.resultIndex) {
CC_EXPECTS(key.camera);
CC_EXPECTS(key.camera->getScene() == scene);
CC_EXPECTS(key.camera->getScene() == nullptr || key.camera->getScene() == scene);
const auto* light = key.light;
const auto level = key.lightLevel;
const auto bCastShadow = key.castShadow;
Expand Down
3 changes: 2 additions & 1 deletion native/cocos/renderer/pipeline/custom/NativeSetter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,12 @@ void NativeSetter::setMat4ArrayElem(const ccstd::string &name, const cc::Mat4 &m

void NativeSetter::setBuiltinCameraConstants(const scene::Camera *camera) {
auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID);
const auto* scene = camera->getScene();
setCameraUBOValues(
*camera,
*layoutGraph,
*pipelineRuntime->getPipelineSceneData(),
camera->getScene()->getMainLight(), data);
scene ? scene->getMainLight() : nullptr, data);
}

void NativeSetter::setBuiltinDirectionalLightFrustumConstants(
Expand Down
Loading

0 comments on commit 2c8aac1

Please sign in to comment.