From ba6076150d1ae19bc1bcbca0aa4f868f4011d3be Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Thu, 27 Jul 2023 16:25:23 +0800 Subject: [PATCH 01/82] fgd rebuild & depth stencil view (#154) --- cocos/gfx/base/define.ts | 3 +- .../cocos/renderer/gfx-base/GFXDef-common.h | 16 +- native/cocos/renderer/gfx-base/GFXTexture.cpp | 2 + native/cocos/renderer/gfx-base/GFXTexture.h | 2 +- .../renderer/gfx-gles3/GLES3Commands.cpp | 19 +- .../renderer/gfx-gles3/GLES3GPUObjects.h | 2 + .../renderer/gfx-gles3/GLES3PipelineState.cpp | 12 +- .../cocos/renderer/gfx-gles3/GLES3Texture.cpp | 2 + .../renderer/gfx-metal/MTLCommandBuffer.mm | 11 +- native/cocos/renderer/gfx-metal/MTLDevice.mm | 2 +- .../renderer/gfx-metal/MTLPipelineState.mm | 5 +- .../cocos/renderer/gfx-metal/MTLRenderPass.mm | 8 +- native/cocos/renderer/gfx-metal/MTLShader.mm | 2 +- native/cocos/renderer/gfx-metal/MTLTexture.mm | 11 +- native/cocos/renderer/gfx-metal/MTLUtils.h | 3 +- native/cocos/renderer/gfx-metal/MTLUtils.mm | 74 +- .../cocos/renderer/gfx-vulkan/VKCommands.cpp | 31 +- .../cocos/renderer/gfx-vulkan/VKGPUObjects.h | 2 + .../cocos/renderer/gfx-vulkan/VKTexture.cpp | 4 + .../pipeline/custom/FGDispatcherGraphs.h | 1786 ++++---- .../pipeline/custom/FGDispatcherTypes.cpp | 280 +- .../pipeline/custom/FGDispatcherTypes.h | 953 ++-- .../pipeline/custom/FrameGraphDispatcher.cpp | 4053 ++++++++--------- .../pipeline/custom/NativeExecutor.cpp | 318 +- .../pipeline/custom/NativePipeline.cpp | 50 +- .../pipeline/custom/NativeRenderGraph.cpp | 36 +- .../pipeline/custom/NativeRenderGraphUtils.h | 13 + .../pipeline/custom/NativeResourceGraph.cpp | 37 +- .../renderer/pipeline/custom/test/test.h | 300 +- .../src/complicated_barrier_case.cpp | 201 +- .../unit-test/src/simple_barrier_test.cpp | 40 +- .../src/simple_closed_barrier_test.cpp | 137 +- 32 files changed, 3945 insertions(+), 4470 deletions(-) diff --git a/cocos/gfx/base/define.ts b/cocos/gfx/base/define.ts index 53eeb4062cb..6e614fb3630 100644 --- a/cocos/gfx/base/define.ts +++ b/cocos/gfx/base/define.ts @@ -407,7 +407,8 @@ export enum TextureFlagBit { GENERAL_LAYOUT = 0x2, // For inout framebuffer attachments EXTERNAL_OES = 0x4, // External oes texture EXTERNAL_NORMAL = 0x8, // External normal texture - LAZILY_ALLOCATED = 0x10 // Try lazily allocated mode. + LAZILY_ALLOCATED = 0x10, // Try lazily allocated mode. + MUTABLE_VIEW_FORMAT = 0x40, // texture view as different format } export enum FormatFeatureBit { diff --git a/native/cocos/renderer/gfx-base/GFXDef-common.h b/native/cocos/renderer/gfx-base/GFXDef-common.h index ab5c7bd810f..a8a6e4b22d2 100644 --- a/native/cocos/renderer/gfx-base/GFXDef-common.h +++ b/native/cocos/renderer/gfx-base/GFXDef-common.h @@ -173,9 +173,8 @@ enum class Feature : uint32_t { MULTIPLE_RENDER_TARGETS, BLEND_MINMAX, COMPUTE_SHADER, - // @deprecated - INPUT_ATTACHMENT_BENEFIT, + INPUT_ATTACHMENT_BENEFIT, // @deprecated SUBPASS_COLOR_INPUT, SUBPASS_DEPTH_STENCIL_INPUT, RASTERIZATION_ORDER_NOCOHERENT, @@ -474,11 +473,12 @@ CC_ENUM_BITWISE_OPERATORS(TextureUsageBit); enum class TextureFlagBit : uint32_t { NONE = 0, - GEN_MIPMAP = 0x1, // Generate mipmaps using bilinear filter - GENERAL_LAYOUT = 0x2, // @deprecated, For inout framebuffer attachments - EXTERNAL_OES = 0x4, // External oes texture - EXTERNAL_NORMAL = 0x8, // External normal texture - LAZILY_ALLOCATED = 0x10 // Try lazily allocated mode. + GEN_MIPMAP = 0x1, // Generate mipmaps using bilinear filter + GENERAL_LAYOUT = 0x2, // @deprecated, For inout framebuffer attachments + EXTERNAL_OES = 0x4, // External oes texture + EXTERNAL_NORMAL = 0x8, // External normal texture + LAZILY_ALLOCATED = 0x10, // Try lazily allocated mode. + MUTABLE_VIEW_FORMAT = 0x40, // texture view as different format }; using TextureFlags = TextureFlagBit; CC_ENUM_BITWISE_OPERATORS(TextureFlagBit); @@ -1089,6 +1089,8 @@ struct ALIGNAS(8) TextureViewInfo { uint32_t levelCount{1}; uint32_t baseLayer{0}; uint32_t layerCount{1}; + uint32_t basePlane{0}; + uint32_t planeCount{1}; #if CC_CPU_ARCH == CC_CPU_ARCH_32 uint32_t _padding{0}; #endif diff --git a/native/cocos/renderer/gfx-base/GFXTexture.cpp b/native/cocos/renderer/gfx-base/GFXTexture.cpp index 0f1a7c2c14d..59432996a07 100644 --- a/native/cocos/renderer/gfx-base/GFXTexture.cpp +++ b/native/cocos/renderer/gfx-base/GFXTexture.cpp @@ -144,6 +144,8 @@ void Texture::updateTextureInfo(const SwapchainTextureInfo &info, Texture *out) out->_viewInfo.layerCount = out->_info.layerCount; out->_viewInfo.baseLevel = 0; out->_viewInfo.levelCount = out->_info.levelCount; + out->_viewInfo.basePlane = 0; + out->_viewInfo.planeCount = info.format == gfx::Format::DEPTH_STENCIL ? 2 : 1; } } // namespace gfx diff --git a/native/cocos/renderer/gfx-base/GFXTexture.h b/native/cocos/renderer/gfx-base/GFXTexture.h index b00defb4fc4..0d29fcfc27d 100644 --- a/native/cocos/renderer/gfx-base/GFXTexture.h +++ b/native/cocos/renderer/gfx-base/GFXTexture.h @@ -51,7 +51,7 @@ class CC_DLL Texture : public GFXObject, public RefCounted { inline ccstd::hash_t getHash() const { return _hash; } // convenient getter for common usages - inline Format getFormat() const { return _info.format; } + inline Format getFormat() const { return _isTextureView ? _viewInfo.format : _info.format; } inline uint32_t getWidth() const { return _info.width; } inline uint32_t getHeight() const { return _info.height; } diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp index afddfc2d1a7..231ed1d3b5e 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp @@ -1375,16 +1375,21 @@ void cmdFuncGLES3CreateRenderPass(GLES3Device * /*device*/, GLES3GPURenderPass * auto &attachments = gpuRenderPass->colorAttachments; auto &drawBuffers = gpuRenderPass->drawBuffers; + bool hasDS = (gpuRenderPass->depthStencilAttachment.format != Format::UNKNOWN); gpuRenderPass->drawBuffers.resize(subPasses.size()); - gpuRenderPass->indices.resize(attachments.size(), INVALID_BINDING); + gpuRenderPass->indices.resize(attachments.size() + hasDS, INVALID_BINDING); for (uint32_t i = 0; i < subPasses.size(); ++i) { auto &sub = subPasses[i]; auto &drawBuffer = drawBuffers[i]; - std::vector visited(gpuRenderPass->colorAttachments.size()); + std::vector visited(gpuRenderPass->colorAttachments.size() + hasDS); for (auto &input : sub.inputs) { visited[input] = true; + if(input == gpuRenderPass->colorAttachments.size()) { + // ds input + continue; + } drawBuffer.emplace_back(gpuRenderPass->indices[input]); } @@ -1411,8 +1416,14 @@ void cmdFuncGLES3CreateRenderPass(GLES3Device * /*device*/, GLES3GPURenderPass * } } - gpuRenderPass->depthStencil = sub.depthStencil; - gpuRenderPass->depthStencilResolve = sub.depthStencilResolve; + + if (sub.depthStencil != gfx::INVALID_BINDING) { + gpuRenderPass->depthStencil = sub.depthStencil; + gpuRenderPass->indices.back() = gpuRenderPass->depthStencil; + } + if (sub.depthStencilResolve != gfx::INVALID_BINDING) { + gpuRenderPass->depthStencilResolve = sub.depthStencilResolve; + } } } diff --git a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h index 169767fe082..0005cf0c6b8 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h +++ b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h @@ -156,6 +156,8 @@ struct GLES3GPUTextureView { Format format = Format::UNKNOWN; uint32_t baseLevel = 0U; uint32_t levelCount = 1U; + uint32_t basePlane = 0U; + uint32_t planeCount = 0U; }; using GLES3GPUTextureViewList = ccstd::vector; diff --git a/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp b/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp index 067c5037471..cd97b6fdf4e 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp @@ -61,14 +61,20 @@ void updateGPUShaderSourceByRenderPass(GLES3GPUShader *gpuShader, GLES3GPURender } CC_ASSERT(subpassIndex < renderPass->subpasses.size()); - if (renderPass->subpasses[subpassIndex].inputs.empty()) { + if (renderPass->subpasses.size() <= 1) { return; } - auto &drawBuffers = renderPass->drawBuffers.at(subpassIndex); + bool dsInput{false}; + if (renderPass->depthStencil != INVALID_BINDING && !renderPass->subpasses[subpassIndex].inputs.empty()) { + const auto &inputs = renderPass->subpasses[subpassIndex].inputs; + // depth stencil input should always lies at the end of index list. + dsInput = inputs.back() == renderPass->depthStencil; + } + auto &drawBuffers = renderPass->drawBuffers.at(subpassIndex); ccstd::string::size_type offset = 0; for (uint32_t i = 0; i < drawBuffers.size(); ++i) { - const char* layoutPrefix = "layout(location = "; + const char *layoutPrefix = "layout(location = "; std::stringstream ss1; ss1 << layoutPrefix << i << ") out"; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp b/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp index 286ef62b78f..2026ec3d019 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp @@ -95,6 +95,8 @@ void GLES3Texture::createTextureView() { _gpuTextureView->format = _viewInfo.format; _gpuTextureView->baseLevel = _viewInfo.baseLevel; _gpuTextureView->levelCount = _viewInfo.levelCount; + _gpuTextureView->basePlane = _viewInfo.basePlane; + _gpuTextureView->planeCount = _viewInfo.planeCount; } void GLES3Texture::doDestroy() { diff --git a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm index 84cd6f958e0..eef51f0eef7 100644 --- a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm +++ b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm @@ -219,7 +219,9 @@ of this software and associated engine source code (the "Software"), a limited, for (size_t i = 0; i < subpasses.size(); ++i) { for (size_t j = 0; j < subpasses[i].inputs.size(); ++j) { uint32_t input = subpasses[i].inputs[j]; - if(input >= colorAttachments.size()) { + if(input >= colorAttachments.size() || + colorAttachments[input].format == Format::DEPTH_STENCIL || + colorAttachments[input].format == Format::DEPTH) { continue; // depthStencil as input } if (visited[input]) @@ -237,7 +239,7 @@ of this software and associated engine source code (the "Software"), a limited, if(color >= colorAttachments.size()) { continue; // depthStencil as output } - if (subpasses[i].resolves.size() > j) { + if (!subpasses[i].resolves.empty() && subpasses[i].resolves[j] != INVALID_BINDING) { uint32_t resolve = subpasses[i].resolves[j]; auto *resolveTex = static_cast(colorTextures[resolve]); mtlRenderPassDescriptor.colorAttachments[color].resolveTexture = resolveTex->getMTLTexture(); @@ -245,6 +247,8 @@ of this software and associated engine source code (the "Software"), a limited, mtlRenderPassDescriptor.colorAttachments[color].resolveSlice = 0; mtlRenderPassDescriptor.colorAttachments[color].resolveDepthPlane = 0; mtlRenderPassDescriptor.colorAttachments[color].storeAction = MTLStoreActionMultisampleResolve; + } else { + mtlRenderPassDescriptor.colorAttachments[color].storeAction = mu::isFramebufferFetchSupported() ? mu::toMTLStoreAction(colorAttachments[color].storeOp) : MTLStoreActionStore; } if (visited[color]) continue; @@ -261,7 +265,6 @@ of this software and associated engine source code (the "Software"), a limited, } else { mtlRenderPassDescriptor.colorAttachments[color].loadAction = mu::toMTLLoadAction(colorAttachments[color].loadOp); } - mtlRenderPassDescriptor.colorAttachments[color].storeAction = mu::isFramebufferFetchSupported() ? mu::toMTLStoreAction(colorAttachments[color].storeOp) : MTLStoreActionStore; visited[color] = true; _colorAppearedBefore.set(color); } @@ -386,7 +389,7 @@ of this software and associated engine source code (the "Software"), a limited, } if (subpass.depthStencilResolve != INVALID_BINDING) { - descriptor.depthAttachment.resolveTexture = static_cast(curFBO->getDepthStencilTexture())->getMTLTexture(); + descriptor.depthAttachment.resolveTexture = static_cast(curFBO->getDepthStencilResolveTexture())->getMTLTexture(); descriptor.depthAttachment.resolveLevel = 0; descriptor.depthAttachment.resolveSlice = 0; descriptor.depthAttachment.resolveDepthPlane = 0; diff --git a/native/cocos/renderer/gfx-metal/MTLDevice.mm b/native/cocos/renderer/gfx-metal/MTLDevice.mm index 186a152bcda..097d14dd0b1 100644 --- a/native/cocos/renderer/gfx-metal/MTLDevice.mm +++ b/native/cocos/renderer/gfx-metal/MTLDevice.mm @@ -135,7 +135,7 @@ of this software and associated engine source code (the "Software"), a limited, _features[toNumber(Feature::ELEMENT_INDEX_UINT)] = true; _features[toNumber(Feature::COMPUTE_SHADER)] = true; _features[toNumber(Feature::INPUT_ATTACHMENT_BENEFIT)] = true; - _features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = false; + _features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = true; _features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = false; _features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true; diff --git a/native/cocos/renderer/gfx-metal/MTLPipelineState.mm b/native/cocos/renderer/gfx-metal/MTLPipelineState.mm index 447ca460e19..5eb009affe0 100644 --- a/native/cocos/renderer/gfx-metal/MTLPipelineState.mm +++ b/native/cocos/renderer/gfx-metal/MTLPipelineState.mm @@ -304,10 +304,11 @@ of this software and associated engine source code (the "Software"), a limited, depthStencilTexIndex = subpass.depthStencil; for (size_t i = 0; i < subpass.inputs.size(); ++i) { uint32_t input = subpass.inputs[i]; + if (inputs.find(input) == inputs.end()) { inputs.insert(input); - if(input >= colorAttachments.size()) { - depthStencilTexIndex = input; + if(_renderPass->getColorAttachments()[input].format == Format::DEPTH || + _renderPass->getColorAttachments()[input].format == Format::DEPTH_STENCIL) { continue; } mtlPixelFormat = mu::toMTLPixelFormat(colorAttachments[input].format); diff --git a/native/cocos/renderer/gfx-metal/MTLRenderPass.mm b/native/cocos/renderer/gfx-metal/MTLRenderPass.mm index 06c177998ea..51b98ea9f3e 100644 --- a/native/cocos/renderer/gfx-metal/MTLRenderPass.mm +++ b/native/cocos/renderer/gfx-metal/MTLRenderPass.mm @@ -93,7 +93,13 @@ of this software and associated engine source code (the "Software"), a limited, auto &drawBuffer = _drawBuffers[i]; for (auto &input : subPass.inputs) { - auto &index = _colorIndices[input]; + auto index = INVALID_BINDING; + if(input < _colorAttachments.size()) { + index = _colorIndices[input]; + } else { + // ds input + index = input; + } CC_ASSERT(index != INVALID_BINDING); // input should not appear before color or depthstencil. readBuffer.emplace_back(index); } diff --git a/native/cocos/renderer/gfx-metal/MTLShader.mm b/native/cocos/renderer/gfx-metal/MTLShader.mm index 3a81909b736..482eb4d61af 100644 --- a/native/cocos/renderer/gfx-metal/MTLShader.mm +++ b/native/cocos/renderer/gfx-metal/MTLShader.mm @@ -169,7 +169,7 @@ of this software and associated engine source code (the "Software"), a limited, const auto &drawBuffer = renderPass != nullptr ? renderPass->getDrawBuffer(subPass) : emptyBuffer; const auto &readBuffer = renderPass != nullptr ? renderPass->getReadBuffer(subPass) : emptyBuffer; ccstd::string mtlShaderSrc = mu::spirv2MSL(spirv->getOutputData(), spirv->getOutputSize() / unitSize, stage.stage, - _gpuShader, drawBuffer, readBuffer); + _gpuShader, renderPass, subPass); NSString* shader = [NSString stringWithUTF8String:mtlShaderSrc.c_str()]; NSError* error = nil; diff --git a/native/cocos/renderer/gfx-metal/MTLTexture.mm b/native/cocos/renderer/gfx-metal/MTLTexture.mm index edab24a636a..7a9810654a0 100644 --- a/native/cocos/renderer/gfx-metal/MTLTexture.mm +++ b/native/cocos/renderer/gfx-metal/MTLTexture.mm @@ -162,8 +162,14 @@ of this software and associated engine source code (the "Software"), a limited, } _convertedFormat = mu::convertGFXPixelFormat(_viewInfo.format); auto mtlTextureType = mu::toMTLTextureType(_viewInfo.type); + + MTLPixelFormat format = mu::toMTLPixelFormat(_convertedFormat); + if(_viewInfo.format == Format::DEPTH_STENCIL) { + format = _viewInfo.basePlane == 0 ? mu::toMTLPixelFormat(_viewInfo.texture->getFormat()) : MTLPixelFormatX32_Stencil8; + } + _mtlTextureView = [static_cast(_viewInfo.texture)->_mtlTexture - newTextureViewWithPixelFormat:mu::toMTLPixelFormat(_convertedFormat) + newTextureViewWithPixelFormat:format textureType:mtlTextureType levels:NSMakeRange(_viewInfo.baseLevel, _viewInfo.levelCount) slices:NSMakeRange(_viewInfo.baseLayer, _viewInfo.layerCount)]; @@ -220,6 +226,9 @@ of this software and associated engine source code (the "Software"), a limited, return false; descriptor.usage = mu::toMTLTextureUsage(_info.usage); + if(hasFlag(_info.flags, TextureFlags::MUTABLE_VIEW_FORMAT)) { + descriptor.usage |= MTLTextureUsagePixelFormatView; + } descriptor.sampleCount = mu::toMTLSampleCount(_info.samples); descriptor.textureType = descriptor.sampleCount > 1 ? MTLTextureType2DMultisample : mu::toMTLTextureType(_info.type); descriptor.mipmapLevelCount = _info.levelCount; diff --git a/native/cocos/renderer/gfx-metal/MTLUtils.h b/native/cocos/renderer/gfx-metal/MTLUtils.h index f055f6de261..18f597b3f3b 100644 --- a/native/cocos/renderer/gfx-metal/MTLUtils.h +++ b/native/cocos/renderer/gfx-metal/MTLUtils.h @@ -71,8 +71,7 @@ MTLSamplerAddressMode toMTLSamplerAddressMode(Address); int toMTLSamplerBorderColor(const Color &); MTLSamplerMinMagFilter toMTLSamplerMinMagFilter(Filter); MTLSamplerMipFilter toMTLSamplerMipFilter(Filter); -ccstd::string spirv2MSL(const uint32_t *ir, size_t word_count, ShaderStageFlagBit shaderType, CCMTLGPUShader *gpuShader, - const ccstd::vector &drawBuffer, const ccstd::vector &readBuffer); +ccstd::string spirv2MSL(const uint32_t *ir, size_t word_count, ShaderStageFlagBit shaderType, CCMTLGPUShader *gpuShader, RenderPass* renderpass, uint32_t subpassIndex); const uint8_t *convertRGB8ToRGBA8(const uint8_t *source, uint32_t length); const uint8_t *convertRGB32FToRGBA32F(const uint8_t *source, uint32_t length); NSUInteger highestSupportedFeatureSet(id device); diff --git a/native/cocos/renderer/gfx-metal/MTLUtils.mm b/native/cocos/renderer/gfx-metal/MTLUtils.mm index d2864e9b917..f78f8535877 100644 --- a/native/cocos/renderer/gfx-metal/MTLUtils.mm +++ b/native/cocos/renderer/gfx-metal/MTLUtils.mm @@ -35,11 +35,14 @@ of this software and associated engine source code (the "Software"), a limited, #include "spirv_cross/spirv_msl.hpp" #include "TargetConditionals.h" #include "base/Log.h" +#include namespace cc { namespace gfx { namespace { +static constexpr bool ENABLE_DS_INPUT = false; + ccstd::unordered_map pipelineMap; ccstd::unordered_map renderPassMap; @@ -918,8 +921,8 @@ void main() { ccstd::string mu::spirv2MSL(const uint32_t *ir, size_t word_count, ShaderStageFlagBit shaderType, CCMTLGPUShader *gpuShader, - const ccstd::vector &drawBuffer, - const ccstd::vector &readBuffer) { + RenderPass* renderPass, + uint32_t subpassIndex) { CCMTLDevice *device = CCMTLDevice::getInstance(); spirv_cross::CompilerMSL msl(ir, word_count); @@ -1056,19 +1059,40 @@ void main() { } } + struct AttachmentDesc{ + uint32_t slot{0}; + std::string name; + }; + AttachmentDesc depthInput, stencilInput; if (executionModel == spv::ExecutionModelFragment) { + auto* ccRenderPass = static_cast(renderPass); + const auto& readBuffer = ccRenderPass ? ccRenderPass->getReadBuffer(subpassIndex) : ccstd::vector{}; if (!resources.subpass_inputs.empty()) { - gpuShader->inputs.resize(resources.subpass_inputs.size()); +// gpuShader->inputs.resize(resources.subpass_inputs.size()); for (size_t i = 0; i < resources.subpass_inputs.size(); i++) { const auto &attachment = resources.subpass_inputs[i]; - gpuShader->inputs[i].name = attachment.name; - auto id = msl.get_decoration(attachment.id, spv::DecorationInputAttachmentIndex); - auto loc = id >= readBuffer.size() ? id : readBuffer[id]; + auto inputIndex = msl.get_decoration(attachment.id, spv::DecorationInputAttachmentIndex); + auto loc = inputIndex >= readBuffer.size() ? inputIndex : readBuffer[inputIndex]; + if(renderPass) { + if(loc == renderPass->getColorAttachments().size()) { + depthInput.slot = inputIndex; + depthInput.name = attachment.name; + continue; + } + if(loc == (renderPass->getColorAttachments().size() + 1)) { + stencilInput.slot = inputIndex; + stencilInput.name = attachment.name; + continue;; + } + } + auto& input = gpuShader->inputs.emplace_back(); + input.name = attachment.name; msl.set_decoration(attachment.id, spv::DecorationInputAttachmentIndex, loc); } } gpuShader->outputs.resize(resources.stage_outputs.size()); + const auto& drawBuffer = renderPass ? ccRenderPass->getDrawBuffer(subpassIndex) : ccstd::vector{}; for (size_t i = 0; i < resources.stage_outputs.size(); i++) { const auto &stageOutput = resources.stage_outputs[i]; auto set = msl.get_decoration(stageOutput.id, spv::DecorationDescriptorSet); @@ -1096,6 +1120,44 @@ void main() { CC_LOG_ERROR("Compile to MSL failed."); CC_LOG_ERROR("%s", output.c_str()); } + if constexpr(ENABLE_DS_INPUT) { + if(!depthInput.name.empty() || !stencilInput.name.empty()) { + auto outIndex = output.find("struct main0_out"); + std::string depthDecl = depthInput.name.empty() ? "" : "\n float depth [[depth(less)]];"; + std::string stencilDecl = stencilInput.name.empty() ? "" : "\n uint stencil [[stencil]];"; + auto dsDecl = "struct DSInput\n{" + depthDecl + stencilDecl + " \n};\n"; + output.insert(outIndex, dsDecl); + bool hasDepth{false}; + if (!depthInput.name.empty()) { + std::string depthName(depthInput.name.substr(1)); + std::string depthInExp = "[, ]*float4 " + depthName + "([^\\)]+\\))\\]\\]"; + std::regex depthInputExp(depthInExp); + output = std::regex_replace(output, depthInputExp, ""); + std::string_view immutableOut{"fragment main0_out"}; + auto entryIndex = output.find(immutableOut); + auto bodyIndex = output.find_first_of("{", entryIndex + 1); + output = output.insert(bodyIndex + 1, + "\nDSInput __dsInput{};\nfloat " + depthName + " = __dsInput.depth;"); + hasDepth = true; + } + if(!stencilInput.name.empty()) { + std::string stencilName(stencilInput.name.substr(1)); + std::string stencilInExp = "[, ]*int4 " + stencilName + "([^\\)]+\\))\\]\\]"; + std::regex stencilInputExp(stencilInExp); + output = std::regex_replace(output, stencilInputExp, ""); + std::string_view immutableOut{"fragment main0_out"}; + auto entryIndex = output.find(immutableOut); + auto bodyIndex = output.find_first_of("{", entryIndex + 1); + std::string declStr = hasDepth ? "" : "\nDSInput __dsInput{};"; + output = output.insert(bodyIndex + 1, + declStr + "\nuint " + stencilName + " = __dsInput.stencil;"); + std::regex usingValExp(stencilName + "\\.[rx]"); + output = std::regex_replace(output, usingValExp, stencilName); + } + + } + } + return output; } diff --git a/native/cocos/renderer/gfx-vulkan/VKCommands.cpp b/native/cocos/renderer/gfx-vulkan/VKCommands.cpp index cf098298382..0468624dd53 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommands.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKCommands.cpp @@ -196,15 +196,31 @@ void cmdFuncCCVKCreateTextureView(CCVKDevice *device, CCVKGPUTextureView *gpuTex if (!gpuTextureView->gpuTexture) return; auto createFn = [device, gpuTextureView](VkImage vkImage, VkImageView *pVkImageView) { + auto format = gpuTextureView->format; + auto mapAspect = [](CCVKGPUTextureView *gpuTextureView) { + auto aspectMask = gpuTextureView->gpuTexture->aspectMask; + if (gpuTextureView->gpuTexture->format == Format::DEPTH_STENCIL) { + uint32_t planeIndex = gpuTextureView->basePlane; + uint32_t planeCount = gpuTextureView->planeCount; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT << planeIndex; + CC_ASSERT(planeIndex + planeCount <= 2); + CC_ASSERT(planeCount > 0); + while (planeCount && --planeCount) { + aspectMask |= (aspectMask << 1); + } + } + return aspectMask; + }; + VkImageViewCreateInfo createInfo{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; createInfo.image = vkImage; createInfo.viewType = mapVkImageViewType(gpuTextureView->type); - createInfo.format = mapVkFormat(gpuTextureView->format, device->gpuDevice()); - createInfo.subresourceRange.aspectMask = gpuTextureView->gpuTexture->aspectMask; + createInfo.subresourceRange.aspectMask = mapAspect(gpuTextureView); createInfo.subresourceRange.baseMipLevel = gpuTextureView->baseLevel; createInfo.subresourceRange.levelCount = gpuTextureView->levelCount; createInfo.subresourceRange.baseArrayLayer = gpuTextureView->baseLayer; createInfo.subresourceRange.layerCount = gpuTextureView->layerCount; + createInfo.format = mapVkFormat(format, device->gpuDevice()); VK_CHECK(vkCreateImageView(device->gpuDevice()->vkDevice, &createInfo, nullptr, pVkImageView)); }; @@ -444,13 +460,13 @@ void cmdFuncCCVKCreateRenderPass(CCVKDevice *device, CCVKGPURenderPass *gpuRende for (uint32_t input : subpassInfo.inputs) { bool appearsInOutput = std::find(subpassInfo.colors.begin(), subpassInfo.colors.end(), input) != subpassInfo.colors.end(); + VkImageLayout layout = appearsInOutput ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkImageAspectFlags aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT; if (input == gpuRenderPass->colorAttachments.size()) { - VkImageLayout layout = subpassInfo.depthStencil != INVALID_BINDING ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - attachmentReferences.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, input, layout, VK_IMAGE_ASPECT_DEPTH_BIT}); - } else { - VkImageLayout layout = appearsInOutput ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - attachmentReferences.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, input, layout, VK_IMAGE_ASPECT_COLOR_BIT}); + layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + aspectFlag = VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; } + attachmentReferences.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, input, layout, aspectFlag}); } for (uint32_t color : subpassInfo.colors) { const VkAttachmentDescription2 &attachment = attachmentDescriptions[color]; @@ -518,7 +534,6 @@ void cmdFuncCCVKCreateRenderPass(CCVKDevice *device, CCVKGPURenderPass *gpuRende offset += subpassInfo.resolves.size(); } } - if (!subpassInfo.preserves.empty()) { desc.preserveAttachmentCount = utils::toUint(subpassInfo.preserves.size()); desc.pPreserveAttachments = subpassInfo.preserves.data(); diff --git a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h index cb386223c67..edb7dfc6f42 100644 --- a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h +++ b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h @@ -188,6 +188,8 @@ struct CCVKGPUTextureView : public CCVKGPUDeviceObject { uint32_t levelCount = 1U; uint32_t baseLayer = 0U; uint32_t layerCount = 1U; + uint32_t basePlane = 0U; + uint32_t planeCount = 1U; ccstd::vector swapchainVkImageViews; diff --git a/native/cocos/renderer/gfx-vulkan/VKTexture.cpp b/native/cocos/renderer/gfx-vulkan/VKTexture.cpp index 5f0a3e85b47..c9b74b170ba 100644 --- a/native/cocos/renderer/gfx-vulkan/VKTexture.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKTexture.cpp @@ -43,6 +43,7 @@ CCVKTexture::~CCVKTexture() { void CCVKTexture::doInit(const TextureInfo & /*info*/) { createTexture(_info.width, _info.height, _size); + _viewInfo.planeCount = _info.format == Format::DEPTH_STENCIL ? 2 : 1; createTextureView(); } @@ -71,6 +72,7 @@ void CCVKTexture::createTexture(uint32_t width, uint32_t height, uint32_t size, _gpuTexture->mipLevels = _info.levelCount; _gpuTexture->samples = _info.samples; _gpuTexture->flags = _info.flags; + bool hasExternalFlag = hasFlag(_gpuTexture->flags, TextureFlagBit::EXTERNAL_NORMAL); if (hasExternalFlag) { _gpuTexture->externalVKImage = reinterpret_cast(_info.externalRes); @@ -90,6 +92,8 @@ void CCVKTexture::createTextureView(bool initGPUTextureView) { _gpuTextureView->levelCount = _viewInfo.levelCount; _gpuTextureView->baseLayer = _viewInfo.baseLayer; _gpuTextureView->layerCount = _viewInfo.layerCount; + _gpuTextureView->basePlane = _viewInfo.basePlane; + _gpuTextureView->planeCount = _viewInfo.planeCount; if (initGPUTextureView) { _gpuTextureView->init(); diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h b/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h index 4050a7fbb5d..c12b37f57bc 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h @@ -1,824 +1,962 @@ -/**************************************************************************** - Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. - - http://www.cocos.com - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#pragma once -#include -#include -#include "cocos/renderer/pipeline/custom/FGDispatcherTypes.h" -#include "cocos/renderer/pipeline/custom/details/GraphImpl.h" -#include "cocos/renderer/pipeline/custom/details/Overload.h" -#include "cocos/renderer/pipeline/custom/details/PathUtils.h" - -namespace cc { - -namespace render { - -// IncidenceGraph -inline ResourceAccessGraph::vertex_descriptor -source(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { - return e.source; -} - -inline ResourceAccessGraph::vertex_descriptor -target(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { - return e.target; -} - -inline std::pair -out_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return std::make_pair( - ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), - ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); -} - -inline ResourceAccessGraph::degree_size_type -out_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getOutEdgeList(u).size()); -} - -inline std::pair -edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, const ResourceAccessGraph& g) noexcept { - const auto& outEdgeList = g.getOutEdgeList(u); - auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), ResourceAccessGraph::OutEdge(v)); - bool hasEdge = (iter != outEdgeList.end()); - return {ResourceAccessGraph::edge_descriptor(u, v), hasEdge}; -} - -// BidirectionalGraph(Directed) -inline std::pair -in_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return std::make_pair( - ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), - ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); -} - -inline ResourceAccessGraph::degree_size_type -in_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getInEdgeList(u).size()); -} - -inline ResourceAccessGraph::degree_size_type -degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { - return in_degree(u, g) + out_degree(u, g); -} - -// AdjacencyGraph -inline std::pair -adjacent_vertices(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - auto edges = out_edges(u, g); - return std::make_pair(ResourceAccessGraph::adjacency_iterator(edges.first, &g), ResourceAccessGraph::adjacency_iterator(edges.second, &g)); -} - -// VertexListGraph -inline std::pair -vertices(const ResourceAccessGraph& g) noexcept { - return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); -} - -inline ResourceAccessGraph::vertices_size_type -num_vertices(const ResourceAccessGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getVertexList().size()); -} - -// EdgeListGraph -inline std::pair -edges(const ResourceAccessGraph& g0) noexcept { - auto& g = const_cast(g0); - return std::make_pair( - ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), - ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); -} - -inline ResourceAccessGraph::edges_size_type -num_edges(const ResourceAccessGraph& g) noexcept { // NOLINT - ResourceAccessGraph::edges_size_type numEdges = 0; - - auto range = vertices(g); - for (auto iter = range.first; iter != range.second; ++iter) { - numEdges += out_degree(*iter, g); - } - return numEdges; -} - -// MutableGraph(Edge) -inline std::pair -add_edge( // NOLINT - ResourceAccessGraph::vertex_descriptor u, - ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) { - auto& outEdgeList = g.getOutEdgeList(u); - outEdgeList.emplace_back(v); - - auto& inEdgeList = g.getInEdgeList(v); - inEdgeList.emplace_back(u); - - return std::make_pair(ResourceAccessGraph::edge_descriptor(u, v), true); -} - -inline void remove_edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) noexcept { // NOLINT - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)), s.outEdges.end()); - t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)), t.inEdges.end()); -} - -inline void remove_edge(ResourceAccessGraph::out_edge_iterator outIter, ResourceAccessGraph& g) noexcept { // NOLINT - auto e = *outIter; - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)); - CC_EXPECTS(inIter != t.inEdges.end()); - t.inEdges.erase(inIter); - s.outEdges.erase(outIter.base()); -} - -inline void remove_edge(ResourceAccessGraph::edge_descriptor e, ResourceAccessGraph& g) noexcept { // NOLINT - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)); - CC_EXPECTS(outIter != s.outEdges.end()); - remove_edge(ResourceAccessGraph::out_edge_iterator(outIter, u), g); -} - -// MutableGraph(Vertex) -inline void clear_out_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - // Bidirectional (OutEdges) - auto& outEdgeList = g.getOutEdgeList(u); - auto outEnd = outEdgeList.end(); - for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { - auto& inEdgeList = g.getInEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - outEdgeList.clear(); -} - -inline void clear_in_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - // Bidirectional (InEdges) - auto& inEdgeList = g.getInEdgeList(u); - auto inEnd = inEdgeList.end(); - for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { - auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - inEdgeList.clear(); -} - -inline void clear_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - clear_out_edges(u, g); - clear_in_edges(u, g); -} - -inline void remove_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - { // UuidGraph - const auto& key = g.passID[u]; - auto num = g.passIndex.erase(key); - CC_ENSURES(num == 1); - for (auto&& pair : g.passIndex) { - auto& v = pair.second; - if (v > u) { - --v; - } - } - } - impl::removeVectorVertex(const_cast(g), u, ResourceAccessGraph::directed_category{}); - - // remove components - g.passID.erase(g.passID.begin() + static_cast(u)); - g.access.erase(g.access.begin() + static_cast(u)); -} - -// MutablePropertyGraph(Vertex) -template -inline ResourceAccessGraph::vertex_descriptor -addVertex(Component0&& c0, Component1&& c1, ResourceAccessGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - const auto& uuid = c0; - auto res = g.passIndex.emplace(uuid, v); - CC_ENSURES(res.second); - } - g.passID.emplace_back(std::forward(c0)); - g.access.emplace_back(std::forward(c1)); - - return v; -} - -template -inline ResourceAccessGraph::vertex_descriptor -addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, Component1&& c1, ResourceAccessGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - std::apply( - [&](const auto&... args) { - auto res = g.passIndex.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); - CC_ENSURES(res.second); - }, - c0); - } - - std::apply( - [&](auto&&... args) { - g.passID.emplace_back(std::forward(args)...); - }, - std::forward(c0)); - - std::apply( - [&](auto&&... args) { - g.access.emplace_back(std::forward(args)...); - }, - std::forward(c1)); - - return v; -} - -// IncidenceGraph -inline RelationGraph::vertex_descriptor -source(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { - return e.source; -} - -inline RelationGraph::vertex_descriptor -target(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { - return e.target; -} - -inline std::pair -out_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return std::make_pair( - RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), - RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); -} - -inline RelationGraph::degree_size_type -out_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getOutEdgeList(u).size()); -} - -inline std::pair -edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, const RelationGraph& g) noexcept { - const auto& outEdgeList = g.getOutEdgeList(u); - auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), RelationGraph::OutEdge(v)); - bool hasEdge = (iter != outEdgeList.end()); - return {RelationGraph::edge_descriptor(u, v), hasEdge}; -} - -// BidirectionalGraph(Directed) -inline std::pair -in_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return std::make_pair( - RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), - RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); -} - -inline RelationGraph::degree_size_type -in_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getInEdgeList(u).size()); -} - -inline RelationGraph::degree_size_type -degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { - return in_degree(u, g) + out_degree(u, g); -} - -// AdjacencyGraph -inline std::pair -adjacent_vertices(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - auto edges = out_edges(u, g); - return std::make_pair(RelationGraph::adjacency_iterator(edges.first, &g), RelationGraph::adjacency_iterator(edges.second, &g)); -} - -// VertexListGraph -inline std::pair -vertices(const RelationGraph& g) noexcept { - return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); -} - -inline RelationGraph::vertices_size_type -num_vertices(const RelationGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getVertexList().size()); -} - -// EdgeListGraph -inline std::pair -edges(const RelationGraph& g0) noexcept { - auto& g = const_cast(g0); - return std::make_pair( - RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), - RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); -} - -inline RelationGraph::edges_size_type -num_edges(const RelationGraph& g) noexcept { // NOLINT - RelationGraph::edges_size_type numEdges = 0; - - auto range = vertices(g); - for (auto iter = range.first; iter != range.second; ++iter) { - numEdges += out_degree(*iter, g); - } - return numEdges; -} - -// MutableGraph(Edge) -inline std::pair -add_edge( // NOLINT - RelationGraph::vertex_descriptor u, - RelationGraph::vertex_descriptor v, RelationGraph& g) { - auto& outEdgeList = g.getOutEdgeList(u); - outEdgeList.emplace_back(v); - - auto& inEdgeList = g.getInEdgeList(v); - inEdgeList.emplace_back(u); - - return std::make_pair(RelationGraph::edge_descriptor(u, v), true); -} - -inline void remove_edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, RelationGraph& g) noexcept { // NOLINT - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)), s.outEdges.end()); - t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)), t.inEdges.end()); -} - -inline void remove_edge(RelationGraph::out_edge_iterator outIter, RelationGraph& g) noexcept { // NOLINT - auto e = *outIter; - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)); - CC_EXPECTS(inIter != t.inEdges.end()); - t.inEdges.erase(inIter); - s.outEdges.erase(outIter.base()); -} - -inline void remove_edge(RelationGraph::edge_descriptor e, RelationGraph& g) noexcept { // NOLINT - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)); - CC_EXPECTS(outIter != s.outEdges.end()); - remove_edge(RelationGraph::out_edge_iterator(outIter, u), g); -} - -// MutableGraph(Vertex) -inline void clear_out_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - // Bidirectional (OutEdges) - auto& outEdgeList = g.getOutEdgeList(u); - auto outEnd = outEdgeList.end(); - for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { - auto& inEdgeList = g.getInEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - outEdgeList.clear(); -} - -inline void clear_in_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - // Bidirectional (InEdges) - auto& inEdgeList = g.getInEdgeList(u); - auto inEnd = inEdgeList.end(); - for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { - auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - inEdgeList.clear(); -} - -inline void clear_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - clear_out_edges(u, g); - clear_in_edges(u, g); -} - -inline void remove_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - { // UuidGraph - const auto& key = g.descID[u]; - auto num = g.vertexMap.erase(key); - CC_ENSURES(num == 1); - for (auto&& pair : g.vertexMap) { - auto& v = pair.second; - if (v > u) { - --v; - } - } - } - impl::removeVectorVertex(const_cast(g), u, RelationGraph::directed_category{}); - - // remove components - g.descID.erase(g.descID.begin() + static_cast(u)); -} - -// MutablePropertyGraph(Vertex) -template -inline RelationGraph::vertex_descriptor -addVertex(Component0&& c0, RelationGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - const auto& uuid = c0; - auto res = g.vertexMap.emplace(uuid, v); - CC_ENSURES(res.second); - } - g.descID.emplace_back(std::forward(c0)); - - return v; -} - -template -inline RelationGraph::vertex_descriptor -addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, RelationGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - std::apply( - [&](const auto&... args) { - auto res = g.vertexMap.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); - CC_ENSURES(res.second); - }, - c0); - } - - std::apply( - [&](auto&&... args) { - g.descID.emplace_back(std::forward(args)...); - }, - std::forward(c0)); - - return v; -} - -} // namespace render - -} // namespace cc - -namespace boost { - -// Vertex Index -template <> -struct property_map { - using const_type = identity_property_map; - using type = identity_property_map; -}; - -// Vertex Component -template <> -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - const cc::render::ResourceAccessGraph, - const ccstd::pmr::vector, - cc::render::RenderGraph::vertex_descriptor, - const cc::render::RenderGraph::vertex_descriptor&>; - using type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - cc::render::ResourceAccessGraph, - ccstd::pmr::vector, - cc::render::RenderGraph::vertex_descriptor, - cc::render::RenderGraph::vertex_descriptor&>; -}; - -// Vertex Component -template <> -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - const cc::render::ResourceAccessGraph, - const ccstd::pmr::vector, - cc::render::ResourceAccessNode, - const cc::render::ResourceAccessNode&>; - using type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - cc::render::ResourceAccessGraph, - ccstd::pmr::vector, - cc::render::ResourceAccessNode, - cc::render::ResourceAccessNode&>; -}; - -// Vertex ComponentMember -template -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< - lvalue_property_map_tag, - const cc::render::ResourceAccessGraph, - const ccstd::pmr::vector, - T, - const T&, - T cc::render::ResourceAccessNode::*>; - using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< - lvalue_property_map_tag, - cc::render::ResourceAccessGraph, - ccstd::pmr::vector, - T, - T&, - T cc::render::ResourceAccessNode::*>; -}; - -// Vertex Index -template <> -struct property_map { - using const_type = identity_property_map; - using type = identity_property_map; -}; - -// Vertex Component -template <> -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - const cc::render::RelationGraph, - const ccstd::pmr::vector, - cc::render::ResourceAccessGraph::vertex_descriptor, - const cc::render::ResourceAccessGraph::vertex_descriptor&>; - using type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - cc::render::RelationGraph, - ccstd::pmr::vector, - cc::render::ResourceAccessGraph::vertex_descriptor, - cc::render::ResourceAccessGraph::vertex_descriptor&>; -}; - -} // namespace boost - -namespace cc { - -namespace render { - -// Vertex Index -inline boost::property_map::const_type -get(boost::vertex_index_t /*tag*/, const ResourceAccessGraph& /*g*/) noexcept { - return {}; -} - -inline boost::property_map::type -get(boost::vertex_index_t /*tag*/, ResourceAccessGraph& /*g*/) noexcept { - return {}; -} - -inline impl::ColorMap -get(ccstd::pmr::vector& colors, const ResourceAccessGraph& /*g*/) noexcept { - return {colors}; -} - -// Vertex Component -inline typename boost::property_map::const_type -get(ResourceAccessGraph::PassIDTag /*tag*/, const ResourceAccessGraph& g) noexcept { - return {g.passID}; -} - -inline typename boost::property_map::type -get(ResourceAccessGraph::PassIDTag /*tag*/, ResourceAccessGraph& g) noexcept { - return {g.passID}; -} - -// Vertex Component -inline typename boost::property_map::const_type -get(ResourceAccessGraph::AccessNodeTag /*tag*/, const ResourceAccessGraph& g) noexcept { - return {g.access}; -} - -inline typename boost::property_map::type -get(ResourceAccessGraph::AccessNodeTag /*tag*/, ResourceAccessGraph& g) noexcept { - return {g.access}; -} - -// Vertex ComponentMember -template -inline typename boost::property_map::const_type -get(T ResourceAccessNode::*memberPointer, const ResourceAccessGraph& g) noexcept { - return {g.access, memberPointer}; -} - -template -inline typename boost::property_map::type -get(T ResourceAccessNode::*memberPointer, ResourceAccessGraph& g) noexcept { - return {g.access, memberPointer}; -} - -// Vertex Constant Getter -template -inline decltype(auto) -get(Tag tag, const ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Mutable Getter -template -inline decltype(auto) -get(Tag tag, ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Setter -template -inline void put( - Tag tag, ResourceAccessGraph& g, - ResourceAccessGraph::vertex_descriptor v, - Args&&... args) { - put(get(tag, g), v, std::forward(args)...); -} - -// UuidGraph -inline ResourceAccessGraph::vertex_descriptor -vertex(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) { - return g.passIndex.at(key); -} - -template -inline ResourceAccessGraph::vertex_descriptor -vertex(const KeyLike& key, const ResourceAccessGraph& g) { - const auto& index = g.passIndex; - auto iter = index.find(key); - if (iter == index.end()) { - throw std::out_of_range("at(key, ResourceAccessGraph) out of range"); - } - return iter->second; -} - -template -inline ResourceAccessGraph::vertex_descriptor -findVertex(const KeyLike& key, const ResourceAccessGraph& g) noexcept { - const auto& index = g.passIndex; - auto iter = index.find(key); - if (iter == index.end()) { - return ResourceAccessGraph::null_vertex(); - } - return iter->second; -} - -inline bool -contains(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) noexcept { - auto iter = g.passIndex.find(key); - return iter != g.passIndex.end(); -} - -template -inline bool -contains(const KeyLike& key, const ResourceAccessGraph& g) noexcept { - auto iter = g.passIndex.find(key); - return iter != g.passIndex.end(); -} - -// MutableGraph(Vertex) -inline ResourceAccessGraph::vertex_descriptor -add_vertex(ResourceAccessGraph& g, const RenderGraph::vertex_descriptor& key) { // NOLINT - return addVertex( - std::piecewise_construct, - std::forward_as_tuple(key), // passID - std::forward_as_tuple(), // access - g); -} - -// Vertex Index -inline boost::property_map::const_type -get(boost::vertex_index_t /*tag*/, const RelationGraph& /*g*/) noexcept { - return {}; -} - -inline boost::property_map::type -get(boost::vertex_index_t /*tag*/, RelationGraph& /*g*/) noexcept { - return {}; -} - -inline impl::ColorMap -get(ccstd::pmr::vector& colors, const RelationGraph& /*g*/) noexcept { - return {colors}; -} - -// Vertex Component -inline typename boost::property_map::const_type -get(RelationGraph::DescIDTag /*tag*/, const RelationGraph& g) noexcept { - return {g.descID}; -} - -inline typename boost::property_map::type -get(RelationGraph::DescIDTag /*tag*/, RelationGraph& g) noexcept { - return {g.descID}; -} - -// Vertex Constant Getter -template -inline decltype(auto) -get(Tag tag, const RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Mutable Getter -template -inline decltype(auto) -get(Tag tag, RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Setter -template -inline void put( - Tag tag, RelationGraph& g, - RelationGraph::vertex_descriptor v, - Args&&... args) { - put(get(tag, g), v, std::forward(args)...); -} - -// UuidGraph -inline RelationGraph::vertex_descriptor -vertex(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) { - return g.vertexMap.at(key); -} - -template -inline RelationGraph::vertex_descriptor -vertex(const KeyLike& key, const RelationGraph& g) { - const auto& index = g.vertexMap; - auto iter = index.find(key); - if (iter == index.end()) { - throw std::out_of_range("at(key, RelationGraph) out of range"); - } - return iter->second; -} - -template -inline RelationGraph::vertex_descriptor -findVertex(const KeyLike& key, const RelationGraph& g) noexcept { - const auto& index = g.vertexMap; - auto iter = index.find(key); - if (iter == index.end()) { - return RelationGraph::null_vertex(); - } - return iter->second; -} - -inline bool -contains(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) noexcept { - auto iter = g.vertexMap.find(key); - return iter != g.vertexMap.end(); -} - -template -inline bool -contains(const KeyLike& key, const RelationGraph& g) noexcept { - auto iter = g.vertexMap.find(key); - return iter != g.vertexMap.end(); -} - -// MutableGraph(Vertex) -inline RelationGraph::vertex_descriptor -add_vertex(RelationGraph& g, const ResourceAccessGraph::vertex_descriptor& key) { // NOLINT - return addVertex( - std::piecewise_construct, - std::forward_as_tuple(key), // descID - g); -} - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#pragma once +#include +#include +#include "cocos/renderer/pipeline/custom/FGDispatcherTypes.h" +#include "cocos/renderer/pipeline/custom/details/GraphImpl.h" +#include "cocos/renderer/pipeline/custom/details/Overload.h" +#include "cocos/renderer/pipeline/custom/details/PathUtils.h" + +namespace cc { + +namespace render { + +// IncidenceGraph +inline ResourceAccessGraph::vertex_descriptor +source(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { + return e.source; +} + +inline ResourceAccessGraph::vertex_descriptor +target(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { + return e.target; +} + +inline std::pair +out_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return std::make_pair( + ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), + ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); +} + +inline ResourceAccessGraph::degree_size_type +out_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getOutEdgeList(u).size()); +} + +inline std::pair +edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, const ResourceAccessGraph& g) noexcept { + const auto& outEdgeList = g.getOutEdgeList(u); + auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), ResourceAccessGraph::OutEdge(v)); + bool hasEdge = (iter != outEdgeList.end()); + return {ResourceAccessGraph::edge_descriptor(u, v), hasEdge}; +} + +// BidirectionalGraph(Directed) +inline std::pair +in_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return std::make_pair( + ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), + ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); +} + +inline ResourceAccessGraph::degree_size_type +in_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getInEdgeList(u).size()); +} + +inline ResourceAccessGraph::degree_size_type +degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { + return in_degree(u, g) + out_degree(u, g); +} + +// AdjacencyGraph +inline std::pair +adjacent_vertices(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + auto edges = out_edges(u, g); + return std::make_pair(ResourceAccessGraph::adjacency_iterator(edges.first, &g), ResourceAccessGraph::adjacency_iterator(edges.second, &g)); +} + +// VertexListGraph +inline std::pair +vertices(const ResourceAccessGraph& g) noexcept { + return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); +} + +inline ResourceAccessGraph::vertices_size_type +num_vertices(const ResourceAccessGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getVertexList().size()); +} + +// EdgeListGraph +inline std::pair +edges(const ResourceAccessGraph& g0) noexcept { + auto& g = const_cast(g0); + return std::make_pair( + ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), + ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); +} + +inline ResourceAccessGraph::edges_size_type +num_edges(const ResourceAccessGraph& g) noexcept { // NOLINT + ResourceAccessGraph::edges_size_type numEdges = 0; + + auto range = vertices(g); + for (auto iter = range.first; iter != range.second; ++iter) { + numEdges += out_degree(*iter, g); + } + return numEdges; +} + +// MutableGraph(Edge) +inline std::pair +add_edge( // NOLINT + ResourceAccessGraph::vertex_descriptor u, + ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) { + auto& outEdgeList = g.getOutEdgeList(u); + outEdgeList.emplace_back(v); + + auto& inEdgeList = g.getInEdgeList(v); + inEdgeList.emplace_back(u); + + return std::make_pair(ResourceAccessGraph::edge_descriptor(u, v), true); +} + +inline void remove_edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) noexcept { // NOLINT + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)), s.outEdges.end()); + t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)), t.inEdges.end()); +} + +inline void remove_edge(ResourceAccessGraph::out_edge_iterator outIter, ResourceAccessGraph& g) noexcept { // NOLINT + auto e = *outIter; + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)); + CC_EXPECTS(inIter != t.inEdges.end()); + t.inEdges.erase(inIter); + s.outEdges.erase(outIter.base()); +} + +inline void remove_edge(ResourceAccessGraph::edge_descriptor e, ResourceAccessGraph& g) noexcept { // NOLINT + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)); + CC_EXPECTS(outIter != s.outEdges.end()); + remove_edge(ResourceAccessGraph::out_edge_iterator(outIter, u), g); +} + +// MutableGraph(Vertex) +inline void clear_out_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + // Bidirectional (OutEdges) + auto& outEdgeList = g.getOutEdgeList(u); + auto outEnd = outEdgeList.end(); + for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { + auto& inEdgeList = g.getInEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + outEdgeList.clear(); +} + +inline void clear_in_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + // Bidirectional (InEdges) + auto& inEdgeList = g.getInEdgeList(u); + auto inEnd = inEdgeList.end(); + for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { + auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + inEdgeList.clear(); +} + +inline void clear_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + clear_out_edges(u, g); + clear_in_edges(u, g); +} + +inline void remove_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + { // UuidGraph + const auto& key = g.passID[u]; + auto num = g.passIndex.erase(key); + CC_ENSURES(num == 1); + for (auto&& pair : g.passIndex) { + auto& v = pair.second; + if (v > u) { + --v; + } + } + } + impl::removeVectorVertex(const_cast(g), u, ResourceAccessGraph::directed_category{}); + + // remove components + g.passID.erase(g.passID.begin() + static_cast(u)); + g.passResource.erase(g.passResource.begin() + static_cast(u)); + g.rpInfo.erase(g.rpInfo.begin() + static_cast(u)); + g.barrier.erase(g.barrier.begin() + static_cast(u)); +} + +// MutablePropertyGraph(Vertex) +template +inline ResourceAccessGraph::vertex_descriptor +addVertex(Component0&& c0, Component1&& c1, Component2&& c2, Component3&& c3, ResourceAccessGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + const auto& uuid = c0; + auto res = g.passIndex.emplace(uuid, v); + CC_ENSURES(res.second); + } + g.passID.emplace_back(std::forward(c0)); + g.passResource.emplace_back(std::forward(c1)); + g.rpInfo.emplace_back(std::forward(c2)); + g.barrier.emplace_back(std::forward(c3)); + + return v; +} + +template +inline ResourceAccessGraph::vertex_descriptor +addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, Component1&& c1, Component2&& c2, Component3&& c3, ResourceAccessGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + std::apply( + [&](const auto&... args) { + auto res = g.passIndex.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); + CC_ENSURES(res.second); + }, + c0); + } + + std::apply( + [&](auto&&... args) { + g.passID.emplace_back(std::forward(args)...); + }, + std::forward(c0)); + + std::apply( + [&](auto&&... args) { + g.passResource.emplace_back(std::forward(args)...); + }, + std::forward(c1)); + + std::apply( + [&](auto&&... args) { + g.rpInfo.emplace_back(std::forward(args)...); + }, + std::forward(c2)); + + std::apply( + [&](auto&&... args) { + g.barrier.emplace_back(std::forward(args)...); + }, + std::forward(c3)); + + return v; +} + +// IncidenceGraph +inline RelationGraph::vertex_descriptor +source(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { + return e.source; +} + +inline RelationGraph::vertex_descriptor +target(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { + return e.target; +} + +inline std::pair +out_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return std::make_pair( + RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), + RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); +} + +inline RelationGraph::degree_size_type +out_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getOutEdgeList(u).size()); +} + +inline std::pair +edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, const RelationGraph& g) noexcept { + const auto& outEdgeList = g.getOutEdgeList(u); + auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), RelationGraph::OutEdge(v)); + bool hasEdge = (iter != outEdgeList.end()); + return {RelationGraph::edge_descriptor(u, v), hasEdge}; +} + +// BidirectionalGraph(Directed) +inline std::pair +in_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return std::make_pair( + RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), + RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); +} + +inline RelationGraph::degree_size_type +in_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getInEdgeList(u).size()); +} + +inline RelationGraph::degree_size_type +degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { + return in_degree(u, g) + out_degree(u, g); +} + +// AdjacencyGraph +inline std::pair +adjacent_vertices(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + auto edges = out_edges(u, g); + return std::make_pair(RelationGraph::adjacency_iterator(edges.first, &g), RelationGraph::adjacency_iterator(edges.second, &g)); +} + +// VertexListGraph +inline std::pair +vertices(const RelationGraph& g) noexcept { + return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); +} + +inline RelationGraph::vertices_size_type +num_vertices(const RelationGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getVertexList().size()); +} + +// EdgeListGraph +inline std::pair +edges(const RelationGraph& g0) noexcept { + auto& g = const_cast(g0); + return std::make_pair( + RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), + RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); +} + +inline RelationGraph::edges_size_type +num_edges(const RelationGraph& g) noexcept { // NOLINT + RelationGraph::edges_size_type numEdges = 0; + + auto range = vertices(g); + for (auto iter = range.first; iter != range.second; ++iter) { + numEdges += out_degree(*iter, g); + } + return numEdges; +} + +// MutableGraph(Edge) +inline std::pair +add_edge( // NOLINT + RelationGraph::vertex_descriptor u, + RelationGraph::vertex_descriptor v, RelationGraph& g) { + auto& outEdgeList = g.getOutEdgeList(u); + outEdgeList.emplace_back(v); + + auto& inEdgeList = g.getInEdgeList(v); + inEdgeList.emplace_back(u); + + return std::make_pair(RelationGraph::edge_descriptor(u, v), true); +} + +inline void remove_edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, RelationGraph& g) noexcept { // NOLINT + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)), s.outEdges.end()); + t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)), t.inEdges.end()); +} + +inline void remove_edge(RelationGraph::out_edge_iterator outIter, RelationGraph& g) noexcept { // NOLINT + auto e = *outIter; + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)); + CC_EXPECTS(inIter != t.inEdges.end()); + t.inEdges.erase(inIter); + s.outEdges.erase(outIter.base()); +} + +inline void remove_edge(RelationGraph::edge_descriptor e, RelationGraph& g) noexcept { // NOLINT + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)); + CC_EXPECTS(outIter != s.outEdges.end()); + remove_edge(RelationGraph::out_edge_iterator(outIter, u), g); +} + +// MutableGraph(Vertex) +inline void clear_out_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + // Bidirectional (OutEdges) + auto& outEdgeList = g.getOutEdgeList(u); + auto outEnd = outEdgeList.end(); + for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { + auto& inEdgeList = g.getInEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + outEdgeList.clear(); +} + +inline void clear_in_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + // Bidirectional (InEdges) + auto& inEdgeList = g.getInEdgeList(u); + auto inEnd = inEdgeList.end(); + for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { + auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + inEdgeList.clear(); +} + +inline void clear_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + clear_out_edges(u, g); + clear_in_edges(u, g); +} + +inline void remove_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + { // UuidGraph + const auto& key = g.descID[u]; + auto num = g.vertexMap.erase(key); + CC_ENSURES(num == 1); + for (auto&& pair : g.vertexMap) { + auto& v = pair.second; + if (v > u) { + --v; + } + } + } + impl::removeVectorVertex(const_cast(g), u, RelationGraph::directed_category{}); + + // remove components + g.descID.erase(g.descID.begin() + static_cast(u)); +} + +// MutablePropertyGraph(Vertex) +template +inline RelationGraph::vertex_descriptor +addVertex(Component0&& c0, RelationGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + const auto& uuid = c0; + auto res = g.vertexMap.emplace(uuid, v); + CC_ENSURES(res.second); + } + g.descID.emplace_back(std::forward(c0)); + + return v; +} + +template +inline RelationGraph::vertex_descriptor +addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, RelationGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + std::apply( + [&](const auto&... args) { + auto res = g.vertexMap.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); + CC_ENSURES(res.second); + }, + c0); + } + + std::apply( + [&](auto&&... args) { + g.descID.emplace_back(std::forward(args)...); + }, + std::forward(c0)); + + return v; +} + +} // namespace render + +} // namespace cc + +namespace boost { + +// Vertex Index +template <> +struct property_map { + using const_type = identity_property_map; + using type = identity_property_map; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::RenderGraph::vertex_descriptor, + const cc::render::RenderGraph::vertex_descriptor&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::RenderGraph::vertex_descriptor, + cc::render::RenderGraph::vertex_descriptor&>; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::ResourceAccessNode, + const cc::render::ResourceAccessNode&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::ResourceAccessNode, + cc::render::ResourceAccessNode&>; +}; + +// Vertex ComponentMember +template +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + T, + const T&, + T cc::render::ResourceAccessNode::*>; + using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + T, + T&, + T cc::render::ResourceAccessNode::*>; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::FGRenderPassInfo, + const cc::render::FGRenderPassInfo&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::FGRenderPassInfo, + cc::render::FGRenderPassInfo&>; +}; + +// Vertex ComponentMember +template +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + T, + const T&, + T cc::render::FGRenderPassInfo::*>; + using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + T, + T&, + T cc::render::FGRenderPassInfo::*>; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::BarrierNode, + const cc::render::BarrierNode&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::BarrierNode, + cc::render::BarrierNode&>; +}; + +// Vertex ComponentMember +template +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + T, + const T&, + T cc::render::BarrierNode::*>; + using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + T, + T&, + T cc::render::BarrierNode::*>; +}; + +// Vertex Index +template <> +struct property_map { + using const_type = identity_property_map; + using type = identity_property_map; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::RelationGraph, + const ccstd::pmr::vector, + cc::render::ResourceAccessGraph::vertex_descriptor, + const cc::render::ResourceAccessGraph::vertex_descriptor&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::RelationGraph, + ccstd::pmr::vector, + cc::render::ResourceAccessGraph::vertex_descriptor, + cc::render::ResourceAccessGraph::vertex_descriptor&>; +}; + +} // namespace boost + +namespace cc { + +namespace render { + +// Vertex Index +inline boost::property_map::const_type +get(boost::vertex_index_t /*tag*/, const ResourceAccessGraph& /*g*/) noexcept { + return {}; +} + +inline boost::property_map::type +get(boost::vertex_index_t /*tag*/, ResourceAccessGraph& /*g*/) noexcept { + return {}; +} + +inline impl::ColorMap +get(ccstd::pmr::vector& colors, const ResourceAccessGraph& /*g*/) noexcept { + return {colors}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::PassIDTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.passID}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::PassIDTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.passID}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::PassNodeTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.passResource}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::PassNodeTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.passResource}; +} + +// Vertex ComponentMember +template +inline typename boost::property_map::const_type +get(T ResourceAccessNode::*memberPointer, const ResourceAccessGraph& g) noexcept { + return {g.passResource, memberPointer}; +} + +template +inline typename boost::property_map::type +get(T ResourceAccessNode::*memberPointer, ResourceAccessGraph& g) noexcept { + return {g.passResource, memberPointer}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::RenderPassInfoTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.rpInfo}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::RenderPassInfoTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.rpInfo}; +} + +// Vertex ComponentMember +template +inline typename boost::property_map::const_type +get(T FGRenderPassInfo::*memberPointer, const ResourceAccessGraph& g) noexcept { + return {g.rpInfo, memberPointer}; +} + +template +inline typename boost::property_map::type +get(T FGRenderPassInfo::*memberPointer, ResourceAccessGraph& g) noexcept { + return {g.rpInfo, memberPointer}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::BarrierTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.barrier}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::BarrierTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.barrier}; +} + +// Vertex ComponentMember +template +inline typename boost::property_map::const_type +get(T BarrierNode::*memberPointer, const ResourceAccessGraph& g) noexcept { + return {g.barrier, memberPointer}; +} + +template +inline typename boost::property_map::type +get(T BarrierNode::*memberPointer, ResourceAccessGraph& g) noexcept { + return {g.barrier, memberPointer}; +} + +// Vertex Constant Getter +template +inline decltype(auto) +get(Tag tag, const ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Mutable Getter +template +inline decltype(auto) +get(Tag tag, ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Setter +template +inline void put( + Tag tag, ResourceAccessGraph& g, + ResourceAccessGraph::vertex_descriptor v, + Args&&... args) { + put(get(tag, g), v, std::forward(args)...); +} + +// UuidGraph +inline ResourceAccessGraph::vertex_descriptor +vertex(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) { + return g.passIndex.at(key); +} + +template +inline ResourceAccessGraph::vertex_descriptor +vertex(const KeyLike& key, const ResourceAccessGraph& g) { + const auto& index = g.passIndex; + auto iter = index.find(key); + if (iter == index.end()) { + throw std::out_of_range("at(key, ResourceAccessGraph) out of range"); + } + return iter->second; +} + +template +inline ResourceAccessGraph::vertex_descriptor +findVertex(const KeyLike& key, const ResourceAccessGraph& g) noexcept { + const auto& index = g.passIndex; + auto iter = index.find(key); + if (iter == index.end()) { + return ResourceAccessGraph::null_vertex(); + } + return iter->second; +} + +inline bool +contains(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) noexcept { + auto iter = g.passIndex.find(key); + return iter != g.passIndex.end(); +} + +template +inline bool +contains(const KeyLike& key, const ResourceAccessGraph& g) noexcept { + auto iter = g.passIndex.find(key); + return iter != g.passIndex.end(); +} + +// MutableGraph(Vertex) +inline ResourceAccessGraph::vertex_descriptor +add_vertex(ResourceAccessGraph& g, const RenderGraph::vertex_descriptor& key) { // NOLINT + return addVertex( + std::piecewise_construct, + std::forward_as_tuple(key), // passID + std::forward_as_tuple(), // passResource + std::forward_as_tuple(), // rpInfo + std::forward_as_tuple(), // barrier + g); +} + +// Vertex Index +inline boost::property_map::const_type +get(boost::vertex_index_t /*tag*/, const RelationGraph& /*g*/) noexcept { + return {}; +} + +inline boost::property_map::type +get(boost::vertex_index_t /*tag*/, RelationGraph& /*g*/) noexcept { + return {}; +} + +inline impl::ColorMap +get(ccstd::pmr::vector& colors, const RelationGraph& /*g*/) noexcept { + return {colors}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(RelationGraph::DescIDTag /*tag*/, const RelationGraph& g) noexcept { + return {g.descID}; +} + +inline typename boost::property_map::type +get(RelationGraph::DescIDTag /*tag*/, RelationGraph& g) noexcept { + return {g.descID}; +} + +// Vertex Constant Getter +template +inline decltype(auto) +get(Tag tag, const RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Mutable Getter +template +inline decltype(auto) +get(Tag tag, RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Setter +template +inline void put( + Tag tag, RelationGraph& g, + RelationGraph::vertex_descriptor v, + Args&&... args) { + put(get(tag, g), v, std::forward(args)...); +} + +// UuidGraph +inline RelationGraph::vertex_descriptor +vertex(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) { + return g.vertexMap.at(key); +} + +template +inline RelationGraph::vertex_descriptor +vertex(const KeyLike& key, const RelationGraph& g) { + const auto& index = g.vertexMap; + auto iter = index.find(key); + if (iter == index.end()) { + throw std::out_of_range("at(key, RelationGraph) out of range"); + } + return iter->second; +} + +template +inline RelationGraph::vertex_descriptor +findVertex(const KeyLike& key, const RelationGraph& g) noexcept { + const auto& index = g.vertexMap; + auto iter = index.find(key); + if (iter == index.end()) { + return RelationGraph::null_vertex(); + } + return iter->second; +} + +inline bool +contains(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) noexcept { + auto iter = g.vertexMap.find(key); + return iter != g.vertexMap.end(); +} + +template +inline bool +contains(const KeyLike& key, const RelationGraph& g) noexcept { + auto iter = g.vertexMap.find(key); + return iter != g.vertexMap.end(); +} + +// MutableGraph(Vertex) +inline RelationGraph::vertex_descriptor +add_vertex(RelationGraph& g, const ResourceAccessGraph::vertex_descriptor& key) { // NOLINT + return addVertex( + std::piecewise_construct, + std::forward_as_tuple(key), // descID + g); +} + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp index 01ba6c84a29..1982760fd0a 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp @@ -1,107 +1,173 @@ -/**************************************************************************** - Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. - - http://www.cocos.com - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#include "FGDispatcherTypes.h" - -namespace cc { - -namespace render { - -ResourceAccessGraph::ResourceAccessGraph(const allocator_type& alloc) noexcept -: _vertices(alloc), - passID(alloc), - access(alloc), - passIndex(alloc), - resourceNames(alloc), - resourceIndex(alloc), - leafPasses(alloc), - culledPasses(alloc), - accessRecord(alloc), - resourceLifeRecord(alloc), - topologicalOrder(alloc), - rpInfos(alloc), - subpassIndex(alloc) {} - -// ContinuousContainer -void ResourceAccessGraph::reserve(vertices_size_type sz) { - _vertices.reserve(sz); - passID.reserve(sz); - access.reserve(sz); -} - -ResourceAccessGraph::Vertex::Vertex(const allocator_type& alloc) noexcept -: outEdges(alloc), - inEdges(alloc) {} - -ResourceAccessGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) -: outEdges(std::move(rhs.outEdges), alloc), - inEdges(std::move(rhs.inEdges), alloc) {} - -ResourceAccessGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) -: outEdges(rhs.outEdges, alloc), - inEdges(rhs.inEdges, alloc) {} - -RelationGraph::RelationGraph(const allocator_type& alloc) noexcept -: _vertices(alloc), - descID(alloc), - vertexMap(alloc) {} - -// ContinuousContainer -void RelationGraph::reserve(vertices_size_type sz) { - _vertices.reserve(sz); - descID.reserve(sz); -} - -RelationGraph::Vertex::Vertex(const allocator_type& alloc) noexcept -: outEdges(alloc), - inEdges(alloc) {} - -RelationGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) -: outEdges(std::move(rhs.outEdges), alloc), - inEdges(std::move(rhs.inEdges), alloc) {} - -RelationGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) -: outEdges(rhs.outEdges, alloc), - inEdges(rhs.inEdges, alloc) {} - -FrameGraphDispatcher::FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& graphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept -: resourceAccessGraph(alloc), - resourceGraph(resourceGraphIn), - graph(graphIn), - layoutGraph(layoutGraphIn), - scratch(scratchIn), - externalResMap(alloc), - relationGraph(alloc) {} - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#include "FGDispatcherTypes.h" + +namespace cc { + +namespace render { + +ResourceAccessNode::ResourceAccessNode(const allocator_type& alloc) noexcept +: resourceStatus(alloc) {} + +ResourceAccessNode::ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc) +: resourceStatus(std::move(rhs.resourceStatus), alloc) {} + +ResourceAccessNode::ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc) +: resourceStatus(rhs.resourceStatus, alloc) {} + +AttachmentInfo::AttachmentInfo(const allocator_type& alloc) noexcept +: parentName(alloc) {} + +AttachmentInfo::AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc) +: parentName(std::move(rhs.parentName), alloc), + attachmentIndex(rhs.attachmentIndex), + isResolveView(rhs.isResolveView) {} + +AttachmentInfo::AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc) +: parentName(rhs.parentName, alloc), + attachmentIndex(rhs.attachmentIndex), + isResolveView(rhs.isResolveView) {} + +FGRenderPassInfo::FGRenderPassInfo(const allocator_type& alloc) noexcept +: orderedViews(alloc), + viewIndex(alloc) {} + +FGRenderPassInfo::FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc) +: colorAccesses(std::move(rhs.colorAccesses)), + dsAccess(rhs.dsAccess), + dsResolveAccess(rhs.dsResolveAccess), + rpInfo(std::move(rhs.rpInfo)), + orderedViews(std::move(rhs.orderedViews), alloc), + viewIndex(std::move(rhs.viewIndex), alloc), + resolveCount(rhs.resolveCount), + uniqueRasterViewCount(rhs.uniqueRasterViewCount) {} + +FGRenderPassInfo::FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc) +: colorAccesses(rhs.colorAccesses), + dsAccess(rhs.dsAccess), + dsResolveAccess(rhs.dsResolveAccess), + rpInfo(rhs.rpInfo), + orderedViews(rhs.orderedViews, alloc), + viewIndex(rhs.viewIndex, alloc), + resolveCount(rhs.resolveCount), + uniqueRasterViewCount(rhs.uniqueRasterViewCount) {} + +ResourceAccessGraph::ResourceAccessGraph(const allocator_type& alloc) noexcept +: _vertices(alloc), + passID(alloc), + passResource(alloc), + rpInfo(alloc), + barrier(alloc), + passIndex(alloc), + resourceNames(alloc), + resourceIndex(alloc), + leafPasses(alloc), + culledPasses(alloc), + resourceLifeRecord(alloc), + topologicalOrder(alloc), + resourceAccess(alloc), + movedTarget(alloc), + movedSourceStatus(alloc) {} + +// ContinuousContainer +void ResourceAccessGraph::reserve(vertices_size_type sz) { + _vertices.reserve(sz); + passID.reserve(sz); + passResource.reserve(sz); + rpInfo.reserve(sz); + barrier.reserve(sz); +} + +ResourceAccessGraph::Vertex::Vertex(const allocator_type& alloc) noexcept +: outEdges(alloc), + inEdges(alloc) {} + +ResourceAccessGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) +: outEdges(std::move(rhs.outEdges), alloc), + inEdges(std::move(rhs.inEdges), alloc) {} + +ResourceAccessGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) +: outEdges(rhs.outEdges, alloc), + inEdges(rhs.inEdges, alloc) {} + +RelationGraph::RelationGraph(const allocator_type& alloc) noexcept +: _vertices(alloc), + descID(alloc), + vertexMap(alloc) {} + +// ContinuousContainer +void RelationGraph::reserve(vertices_size_type sz) { + _vertices.reserve(sz); + descID.reserve(sz); +} + +RelationGraph::Vertex::Vertex(const allocator_type& alloc) noexcept +: outEdges(alloc), + inEdges(alloc) {} + +RelationGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) +: outEdges(std::move(rhs.outEdges), alloc), + inEdges(std::move(rhs.inEdges), alloc) {} + +RelationGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) +: outEdges(rhs.outEdges, alloc), + inEdges(rhs.inEdges, alloc) {} + +RenderingInfo::RenderingInfo(const allocator_type& alloc) noexcept +: clearColors(alloc) {} + +RenderingInfo::RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc) +: renderpassInfo(std::move(rhs.renderpassInfo)), + framebufferInfo(std::move(rhs.framebufferInfo)), + clearColors(std::move(rhs.clearColors), alloc), + clearDepth(rhs.clearDepth), + clearStencil(rhs.clearStencil) {} + +RenderingInfo::RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc) +: renderpassInfo(rhs.renderpassInfo), + framebufferInfo(rhs.framebufferInfo), + clearColors(rhs.clearColors, alloc), + clearDepth(rhs.clearDepth), + clearStencil(rhs.clearStencil) {} + +FrameGraphDispatcher::FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept +: resourceAccessGraph(alloc), + resourceGraph(resourceGraphIn), + renderGraph(renderGraphIn), + layoutGraph(layoutGraphIn), + scratch(scratchIn), + relationGraph(alloc) {} + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h index 0ac3830c647..25816eaf81c 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h @@ -1,451 +1,502 @@ -/**************************************************************************** - Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. - - http://www.cocos.com - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#pragma once -#include -#include -#include -#include -#include -#include "cocos/base/std/container/string.h" -#include "cocos/base/std/container/vector.h" -#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" -#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/Map.h" -#include "cocos/renderer/pipeline/custom/details/Set.h" -#include "gfx-base/GFXDef-common.h" - -namespace cc { - -namespace render { - -struct NullTag { -}; - -struct ResourceLifeRecord { - uint32_t start{0}; - uint32_t end{0}; -}; - -struct LeafStatus { - bool isExternal{false}; - bool needCulling{false}; -}; - -struct BufferRange { - uint32_t offset{0}; - uint32_t size{0}; -}; - -inline bool operator<(const BufferRange& lhs, const BufferRange& rhs) noexcept { - return std::forward_as_tuple(lhs.offset, lhs.size) < - std::forward_as_tuple(rhs.offset, rhs.size); -} - -struct TextureRange { - uint32_t firstSlice{0}; - uint32_t numSlices{1}; - uint32_t mipLevel{0}; - uint32_t levelCount{1}; -}; - -inline bool operator<(const TextureRange& lhs, const TextureRange& rhs) noexcept { - return std::forward_as_tuple(lhs.firstSlice, lhs.numSlices, lhs.mipLevel, lhs.levelCount) < - std::forward_as_tuple(rhs.firstSlice, rhs.numSlices, rhs.mipLevel, rhs.levelCount); -} - -using Range = ccstd::variant; - -using ResourceUsage = ccstd::variant; - -struct AccessStatus { - uint32_t vertID{0xFFFFFFFF}; - gfx::ShaderStageFlagBit visibility{gfx::ShaderStageFlagBit::NONE}; - gfx::MemoryAccessBit access{gfx::MemoryAccessBit::NONE}; - gfx::PassType passType{gfx::PassType::RASTER}; - gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; - ResourceUsage usage; - Range range; -}; - -struct ResourceTransition { - AccessStatus lastStatus; - AccessStatus currStatus; -}; - -struct ResourceAccessNode { - std::vector attachmentStatus; - struct ResourceAccessNode* nextSubpass{nullptr}; -}; - -struct LayoutAccess { - gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; - gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; -}; - -struct FGRenderPassInfo { - std::vector colorAccesses; - LayoutAccess dsAccess; - LayoutAccess dsResolveAccess; - gfx::RenderPassInfo rpInfo; - std::vector orderedViews; - bool needResolve{false}; -}; - -struct ResourceAccessGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT - ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - ~ResourceAccessGraph() { - for (auto& node : access) { - auto* resNode = node.nextSubpass; - node.nextSubpass = nullptr; - while(resNode) { - auto* oldResNode = resNode; - resNode = resNode->nextSubpass; - oldResNode->nextSubpass = nullptr; - delete oldResNode; - } - } - } - - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct PassIDTag {}; - struct AccessNodeTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector passID; - ccstd::pmr::vector access; - // UuidGraph - PmrUnorderedMap passIndex; - // Members - ccstd::pmr::vector resourceNames; - PmrUnorderedStringMap resourceIndex; - vertex_descriptor presentPassID{0xFFFFFFFF}; - PmrFlatMap leafPasses; - PmrFlatSet culledPasses; - PmrFlatMap accessRecord; - PmrFlatMap resourceLifeRecord; - ccstd::pmr::vector topologicalOrder; - PmrFlatMap rpInfos; - PmrFlatMap subpassIndex; -}; - -struct RelationGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - RelationGraph(const allocator_type& alloc) noexcept; // NOLINT - RelationGraph(RelationGraph&& rhs) = delete; - RelationGraph(RelationGraph const& rhs) = delete; - RelationGraph& operator=(RelationGraph&& rhs) = delete; - RelationGraph& operator=(RelationGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - RelationGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct DescIDTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector descID; - // UuidGraph - PmrUnorderedMap vertexMap; -}; - -struct Barrier { - ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; - gfx::BarrierType type{gfx::BarrierType::FULL}; - gfx::GFXObject* barrier{nullptr}; - AccessStatus beginStatus; - AccessStatus endStatus; -}; - -struct BarrierPair { - std::vector frontBarriers; - std::vector rearBarriers; -}; - -struct BarrierNode { - BarrierPair blockBarrier; - std::vector subpassBarriers; -}; - -struct FrameGraphDispatcher { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {resourceAccessGraph.get_allocator().resource()}; - } - - FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& graphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; - FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; - - using BarrierMap = PmrMap; - - void enablePassReorder(bool enable); - - // how much paralell-execution weights during pass reorder, - // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. - // 0 by default - void setParalellWeight(float paralellExecWeight); - - void enableMemoryAliasing(bool enable); - - void run(); - - const ResourceAccessNode& getAttachmentStatus(RenderGraph::vertex_descriptor renderGraphVertID) const; - - inline const BarrierMap& getBarriers() const { return barrierMap; } - - BarrierMap barrierMap; - - ResourceAccessGraph resourceAccessGraph; - ResourceGraph& resourceGraph; - const RenderGraph& graph; - const LayoutGraphData& layoutGraph; - boost::container::pmr::memory_resource* scratch{nullptr}; - PmrFlatMap externalResMap; - RelationGraph relationGraph; - bool _enablePassReorder{false}; - bool _enableAutoBarrier{true}; - bool _enableMemoryAliasing{false}; - bool _accessGraphBuilt{false}; - float _paralellExecWeight{0.0F}; -}; - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#pragma once +#include +#include +#include +#include +#include +#include "cocos/base/std/container/string.h" +#include "cocos/base/std/container/vector.h" +#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" +#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/Map.h" +#include "cocos/renderer/pipeline/custom/details/Set.h" +#include "gfx-base/GFXDef-common.h" + +namespace cc { + +namespace render { + +struct NullTag { +}; + +struct ResourceLifeRecord { + uint32_t start{0}; + uint32_t end{0}; +}; + +struct LeafStatus { + bool isExternal{false}; + bool needCulling{false}; +}; + +struct ResourceRange { + uint32_t width{0}; + uint32_t height{0}; + uint32_t depthOrArraySize{0}; + uint32_t firstSlice{0}; + uint32_t numSlices{0}; + uint32_t mipLevel{0}; + uint32_t levelCount{0}; + uint32_t basePlane{0}; + uint32_t planeCount{0}; +}; + +struct AccessStatus { + gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; + ResourceRange range; +}; + +struct ResourceAccessNode { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceStatus.get_allocator().resource()}; + } + + ResourceAccessNode(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc); + ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc); + + ResourceAccessNode(ResourceAccessNode&& rhs) noexcept = default; + ResourceAccessNode(ResourceAccessNode const& rhs) = delete; + ResourceAccessNode& operator=(ResourceAccessNode&& rhs) = default; + ResourceAccessNode& operator=(ResourceAccessNode const& rhs) = default; + + PmrFlatMap resourceStatus; +}; + +struct LayoutAccess { + gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; + gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; +}; + +struct AttachmentInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {parentName.get_allocator().resource()}; + } + + AttachmentInfo(const allocator_type& alloc) noexcept; // NOLINT + AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc); + AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc); + + AttachmentInfo(AttachmentInfo&& rhs) noexcept = default; + AttachmentInfo(AttachmentInfo const& rhs) = delete; + AttachmentInfo& operator=(AttachmentInfo&& rhs) = default; + AttachmentInfo& operator=(AttachmentInfo const& rhs) = default; + + ccstd::pmr::string parentName; + uint32_t attachmentIndex{0}; + uint32_t isResolveView{0}; +}; + +struct FGRenderPassInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {orderedViews.get_allocator().resource()}; + } + + FGRenderPassInfo(const allocator_type& alloc) noexcept; // NOLINT + FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc); + FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc); + + FGRenderPassInfo(FGRenderPassInfo&& rhs) noexcept = default; + FGRenderPassInfo(FGRenderPassInfo const& rhs) = delete; + FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; + FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; + + std::vector colorAccesses; + LayoutAccess dsAccess; + LayoutAccess dsResolveAccess; + gfx::RenderPassInfo rpInfo; + ccstd::pmr::vector orderedViews; + PmrTransparentMap viewIndex; + uint32_t resolveCount{0}; + uint32_t uniqueRasterViewCount{0}; +}; + +struct Barrier { + ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; + gfx::BarrierType type{gfx::BarrierType::FULL}; + gfx::GFXObject* barrier{nullptr}; + RenderGraph::vertex_descriptor beginVert{0xFFFFFFFF}; + RenderGraph::vertex_descriptor endVert{0xFFFFFFFF}; + AccessStatus beginStatus; + AccessStatus endStatus; +}; + +struct BarrierNode { + std::vector frontBarriers; + std::vector rearBarriers; +}; + +struct ResourceAccessGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + LayoutAccess getAccess(ccstd::pmr::string, RenderGraph::vertex_descriptor vertID); + + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct PassIDTag {}; + struct PassNodeTag {}; + struct RenderPassInfoTag {}; + struct BarrierTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector passID; + ccstd::pmr::vector passResource; + ccstd::pmr::vector rpInfo; + ccstd::pmr::vector barrier; + // UuidGraph + PmrUnorderedMap passIndex; + // Members + ccstd::pmr::vector resourceNames; + PmrUnorderedStringMap resourceIndex; + vertex_descriptor presentPassID{0xFFFFFFFF}; + PmrFlatMap leafPasses; + PmrFlatSet culledPasses; + PmrFlatMap resourceLifeRecord; + ccstd::pmr::vector topologicalOrder; + PmrTransparentMap> resourceAccess; + PmrFlatMap> movedTarget; + PmrFlatMap movedSourceStatus; +}; + +struct RelationGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + RelationGraph(const allocator_type& alloc) noexcept; // NOLINT + RelationGraph(RelationGraph&& rhs) = delete; + RelationGraph(RelationGraph const& rhs) = delete; + RelationGraph& operator=(RelationGraph&& rhs) = delete; + RelationGraph& operator=(RelationGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + RelationGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct DescIDTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector descID; + // UuidGraph + PmrUnorderedMap vertexMap; +}; + +struct RenderingInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {clearColors.get_allocator().resource()}; + } + + RenderingInfo(const allocator_type& alloc) noexcept; // NOLINT + RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc); + RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc); + + RenderingInfo(RenderingInfo&& rhs) noexcept = default; + RenderingInfo(RenderingInfo const& rhs) = delete; + RenderingInfo& operator=(RenderingInfo&& rhs) = default; + RenderingInfo& operator=(RenderingInfo const& rhs) = default; + + gfx::RenderPassInfo renderpassInfo; + gfx::FramebufferInfo framebufferInfo; + ccstd::pmr::vector clearColors; + float clearDepth{0}; + uint8_t clearStencil{0}; +}; + +struct FrameGraphDispatcher { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceAccessGraph.get_allocator().resource()}; + } + + FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; + FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; + + + void enablePassReorder(bool enable); + + // how much paralell-execution weights during pass reorder, + // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. + // 0 by default + void setParalellWeight(float paralellExecWeight); + + void enableMemoryAliasing(bool enable); + + void run(); + + const BarrierNode& getBarrier(RenderGraph::vertex_descriptor u) const; + + const ResourceAccessNode& getAccessNode(RenderGraph::vertex_descriptor u) const; + + const gfx::RenderPassInfo& getRenderPassInfo(RenderGraph::vertex_descriptor u) const; + + RenderingInfo getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph& resg) const; + + LayoutAccess getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const; + + // those resource been moved point to another resID + ResourceGraph::vertex_descriptor realResourceID(const ccstd::pmr::string& name) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + const PmrTransparentMap& rasterViews, + boost::container::pmr::memory_resource* scratch) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + boost::container::pmr::memory_resource* scratch) const; + + ResourceAccessGraph resourceAccessGraph; + ResourceGraph& resourceGraph; + const RenderGraph& renderGraph; + const LayoutGraphData& layoutGraph; + boost::container::pmr::memory_resource* scratch{nullptr}; + RelationGraph relationGraph; + bool _enablePassReorder{false}; + bool _enableAutoBarrier{true}; + bool _enableMemoryAliasing{false}; + bool _accessGraphBuilt{false}; + float _paralellExecWeight{0.0F}; +}; + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 1a2cffac76a..af02a891d01 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include "boost/graph/hawick_circuits.hpp" #include "boost/graph/visitors.hpp" #include "boost/lexical_cast.hpp" +#include "details/GraphView.h" #include "details/Range.h" #include "gfx-base/GFXBarrier.h" #include "gfx-base/GFXDef-common.h" @@ -54,11 +56,20 @@ #include "pipeline/custom/RenderCommonFwd.h" #include "pipeline/custom/RenderGraphTypes.h" #include "pipeline/custom/details/GslUtils.h" +#include "NativeRenderGraphUtils.h" #ifndef BRANCH_CULLING #define BRANCH_CULLING 0 #endif +#define ENABLE_FGD_WARNNING 1 + +#ifdef ENABLE_FGD_WARNNING + #define FGD_WARNING(...) printf(##__VA_ARGS__) +#else + #define FGD_WARNING(...) +#endif + namespace cc { namespace render { @@ -91,35 +102,217 @@ void FrameGraphDispatcher::setParalellWeight(float paralellExecWeight) { _paralellExecWeight = clampf(paralellExecWeight, 0.0F, 1.0F); } -const ResourceAccessNode &FrameGraphDispatcher::getAttachmentStatus(RenderGraph::vertex_descriptor renderGraphVertID) const { - auto iter = resourceAccessGraph.subpassIndex.find(renderGraphVertID); - auto ragVertID = resourceAccessGraph.passIndex.at(renderGraphVertID); - const ResourceAccessNode *accessNode = &resourceAccessGraph.access.at(ragVertID); - if (iter != resourceAccessGraph.subpassIndex.end()) { - auto subpassIndex = iter->second; - accessNode = accessNode->nextSubpass; - CC_ASSERT(accessNode); - while (subpassIndex) { - accessNode = accessNode->nextSubpass; - --subpassIndex; - CC_ASSERT(accessNode); +const BarrierNode &FrameGraphDispatcher::getBarrier(RenderGraph::vertex_descriptor u) const { + auto ragVertID = resourceAccessGraph.passIndex.at(u); + return get(ResourceAccessGraph::BarrierTag{}, resourceAccessGraph, ragVertID); +} + +const ResourceAccessNode &FrameGraphDispatcher::getAccessNode(RenderGraph::vertex_descriptor u) const { + auto ragVertID = resourceAccessGraph.passIndex.at(u); + return get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, ragVertID); +} + +const gfx::RenderPassInfo &FrameGraphDispatcher::getRenderPassInfo(RenderGraph::vertex_descriptor u) const { + CC_EXPECTS(holds(u, renderGraph)); + auto ragVertID = resourceAccessGraph.passIndex.at(u); + return get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, ragVertID).rpInfo; +} + +ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccstd::pmr::string &name) const { + return resourceAccessGraph.resourceIndex.at(name); +} + +ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, const ResourceGraph &resg, std::string_view name) { + auto resName = get(ResourceGraph::NameTag{}, resg, resID); + resName += "/"; + resName += name; + return findVertex(resName, resg); +} + +ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, + const ResourceGraph &resg, + uint32_t basePlane) { + auto ret = resID; + const auto &desc = get(ResourceGraph::DescTag{}, resg, resID); + if (desc.format == gfx::Format::DEPTH_STENCIL) { + ret = basePlane == 0 ? locateSubres(resID, resg, DEPTH_PLANE_NAME) : locateSubres(resID, resg, STENCIL_PLANE_NAME); + } + return ret; +} + +PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( + const PmrTransparentMap> &computeViews, + boost::container::pmr::memory_resource *scratch) const { + PmrFlatMap resourceIndex(scratch); + resourceIndex.reserve(computeViews.size() * 2); + if (!computeViews.empty()) { + for (const auto &[resName, computeViews] : computeViews) { + auto resID = realResourceID(resName); + for (const auto &computeView : computeViews) { + const auto &name = computeView.name; + CC_EXPECTS(!name.empty()); + const auto nameID = layoutGraph.attributeIndex.at(name); + auto subresID = locateSubres(resID, resourceGraph, computeView.plane); + resourceIndex.emplace(nameID, subresID); + } + } + } + return resourceIndex; +} + +PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( + const PmrTransparentMap> &computeViews, + const PmrTransparentMap &rasterViews, + boost::container::pmr::memory_resource *scratch) const { + + auto resourceIndex = buildDescriptorIndex(computeViews, scratch); + if (!rasterViews.empty()) { + NameLocalID unused{128}; + // input sort by slot name + ccstd::pmr::map> inputs(scratch); + for (const auto &[resourceName, rasterView] : rasterViews) { + if (rasterView.accessType != AccessType::WRITE) { + if (!defaultAttachment(rasterView.slotName)) { + std::string_view suffix = rasterView.attachmentType == AttachmentType::DEPTH_STENCIL ? DEPTH_PLANE_NAME : ""; + inputs.emplace(std::piecewise_construct, + std::forward_as_tuple(rasterView.slotName), + std::forward_as_tuple(resourceName, suffix)); + } + if (!defaultAttachment(rasterView.slotName1)) { + CC_EXPECTS(rasterView.attachmentType == AttachmentType::DEPTH_STENCIL); + std::string_view suffix = STENCIL_PLANE_NAME; + inputs.emplace(std::piecewise_construct, + std::forward_as_tuple(rasterView.slotName1), + std::forward_as_tuple(resourceName, suffix)); + } + } + } + // build pass resources + for (const auto &[slotName, nameInfo] : inputs) { + auto resID = realResourceID(nameInfo.first); + resID = locateSubres(resID, resourceGraph, nameInfo.second); + resourceIndex.emplace(unused, resID); + unused.value++; } } - return *accessNode; + + return resourceIndex; +} + +RenderingInfo FrameGraphDispatcher::getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph &resg) const { + auto ragVertID = resourceAccessGraph.passIndex.at(u); + const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, ragVertID); + const auto &orderedViews = fgRenderPassInfo.orderedViews; + const auto &viewIndex = fgRenderPassInfo.viewIndex; + + RenderingInfo renderingInfo(scratch); + renderingInfo.renderpassInfo = getRenderPassInfo(u); + gfx::FramebufferInfo fbInfo{ + nullptr, + }; + + CC_ENSURES(holds(u, renderGraph)); + const RasterPass &pass = get(RasterPassTag{}, u, renderGraph); + + for (const auto &viewName : orderedViews) { + const auto &info = viewIndex.at(viewName); + auto attachmentIndex = info.attachmentIndex; + gfx::Color clearColor{}; + if (!info.isResolveView) { + const auto &rasterView = pass.rasterViews.at(viewName); + clearColor = rasterView.clearColor; + } + if (info.attachmentIndex != gfx::INVALID_BINDING) { + // colorLike + renderingInfo.clearColors.emplace_back(clearColor); + + auto resID = resourceAccessGraph.resourceIndex.at(viewName); + visitObject( + resID, resg, + [&](const ManagedResource &res) { + std::ignore = res; + CC_EXPECTS(false); + }, + [&](const ManagedBuffer &res) { + std::ignore = res; + CC_EXPECTS(false); + }, + [&](const ManagedTexture &tex) { + CC_EXPECTS(tex.texture); + fbInfo.colorTextures.emplace_back(tex.texture); + }, + [&](const IntrusivePtr &res) { + std::ignore = res; + CC_EXPECTS(false); + }, + [&](const IntrusivePtr &tex) { + fbInfo.colorTextures.emplace_back(tex); + }, + [&](const IntrusivePtr &fb) { + CC_EXPECTS(fb->getColorTextures().size() == 1); + CC_EXPECTS(fb->getColorTextures().at(0)); + // render window attaches a depthStencil by default, which may differs from renderpassInfo here. + // data.framebuffer = fb; + }, + [&](const RenderSwapchain &sc) { + fbInfo.colorTextures.emplace_back(sc.swapchain->getColorTexture()); + }, + [&](const FormatView &view) { + // TODO(zhouzhenglong): add ImageView support + std::ignore = view; + CC_EXPECTS(false); + }, + [&](const SubresourceView &view) { + fbInfo.colorTextures.emplace_back(view.textureView); + }); + } else { + // ds or ds resolve + if (!info.isResolveView) { + renderingInfo.clearDepth = clearColor.x; + renderingInfo.clearStencil = static_cast(clearColor.y); + } + + auto &dsAttachment = info.isResolveView ? fbInfo.depthStencilResolveTexture : fbInfo.depthStencilTexture; + + auto resID = resourceAccessGraph.resourceIndex.at(viewName); + visitObject( + resID, resg, + [&](const ManagedTexture &tex) { + CC_EXPECTS(tex.texture); + dsAttachment = tex.texture.get(); + }, + [&](const IntrusivePtr &tex) { + dsAttachment = tex.get(); + }, + [&](const FormatView &view) { + std::ignore = view; + CC_EXPECTS(false); + }, + [&](const SubresourceView &view) { + std::ignore = view; + CC_EXPECTS(false); + }, + [](const auto & /*unused*/) { + CC_EXPECTS(false); + }); + } + } + renderingInfo.framebufferInfo = fbInfo; + + return renderingInfo; +} + +LayoutAccess FrameGraphDispatcher::getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const { + auto ragVertID = resourceAccessGraph.passIndex.at(p); + const auto &resName = get(ResourceGraph::NameTag{}, resourceGraph, r); + auto range = resourceAccessGraph.resourceAccess.at(resName).equal_range(ragVertID); + return {range.first->second.accessFlag, range.second->second.accessFlag}; } /////////////////////////////////////////////////////////////////////////////////////INTERNAL⚡IMPLEMENTATION///////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------predefine------------------------------------------------------------------ using PmrString = ccstd::pmr::string; -using RAG = ResourceAccessGraph; -using LGD = LayoutGraphData; -using gfx::PassType; -using BarrierMap = FrameGraphDispatcher::BarrierMap; -using AccessVertex = ResourceAccessGraph::vertex_descriptor; -using InputStatusTuple = std::tuple; -using ResourceHandle = ResourceGraph::vertex_descriptor; -using ResourceNames = PmrFlatSet; using EdgeList = std::pair; using CloseCircuit = std::pair; using CloseCircuits = std::vector; @@ -134,30 +327,23 @@ using ResourceLifeRecordMap = PmrFlatMap; struct Graphs { const RenderGraph &renderGraph; - ResourceGraph &resourceGraph; const LayoutGraphData &layoutGraphData; + ResourceGraph &resourceGraph; ResourceAccessGraph &resourceAccessGraph; RelationGraph &relationGraph; }; struct ViewStatus { - PmrString name; - const PassType passType; + const ccstd::pmr::string &name; + const AccessType access; const gfx::ShaderStageFlagBit visibility; - const gfx::MemoryAccessBit access; const gfx::AccessFlags accessFlag; - const ResourceUsage usage; + const ResourceRange ⦥ }; -auto defaultAccess = gfx::MemoryAccessBit::NONE; -auto defaultVisibility = gfx::ShaderStageFlagBit::NONE; - constexpr uint32_t EXPECT_START_ID = 0; constexpr uint32_t INVALID_ID = 0xFFFFFFFF; -using AccessTable = PmrFlatMap; -using ExternalResMap = PmrFlatMap; - // for scoped enum only template class GfxTypeConverter { @@ -168,39 +354,11 @@ class GfxTypeConverter { } }; -// static auto toGfxAccess = GfxTypeConverter(); -gfx::MemoryAccessBit toGfxAccess(AccessType type) { - switch (type) { - case AccessType::READ: - return gfx::MemoryAccessBit::READ_ONLY; - case AccessType::WRITE: - return gfx::MemoryAccessBit::WRITE_ONLY; - case AccessType::READ_WRITE: - return gfx::MemoryAccessBit::READ_WRITE; - default: - return gfx::MemoryAccessBit::NONE; - } -}; - // TODO(Zeqiang): remove barrier in renderpassinfo gfx::GeneralBarrier *getGeneralBarrier(gfx::Device *device, gfx::AccessFlagBit prevAccess, gfx::AccessFlagBit nextAccess) { return device->getGeneralBarrier({prevAccess, nextAccess}); } -// AccessStatus.vertID : in resourceNode it's resource ID; in barrierNode it's pass ID. -AccessVertex dependencyCheck(RAG &rag, AccessVertex curVertID, const ResourceGraph &rg, const ViewStatus &status); -gfx::ShaderStageFlagBit getVisibilityByDescName(const RenderGraph &renderGraph, const LGD &lgd, uint32_t passID, const PmrString &resName); - -PmrString addAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status); -void addCopyAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status, const Range &range); -void processRasterPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass); -void processComputePass(const Graphs &graphs, uint32_t passID, const ComputePass &pass); -void processRasterSubpass(const Graphs &graphs, uint32_t passID, const RasterSubpass &pass); -void processComputeSubpass(const Graphs &graphs, uint32_t passID, const ComputeSubpass &pass); -void processCopyPass(const Graphs &graphs, uint32_t passID, const CopyPass &pass); -void processRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass &pass); -auto getResourceStatus(PassType passType, const PmrString &name, gfx::MemoryAccess memAccess, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph, bool rasterized); - // execution order BUT NOT LOGICALLY bool isPassExecAdjecent(uint32_t passLID, uint32_t passRID) { return std::abs(static_cast(passLID) - static_cast(passRID)) <= 1; @@ -235,11 +393,21 @@ inline bool isAttachmentAccess(gfx::AccessFlagBit flag) { gfx::AccessFlagBit::DEPTH_STENCIL_ATTACHMENT_WRITE); } +// SHADING_RATE may be ambiguos inline bool isReadOnlyAccess(gfx::AccessFlagBit flag) { - return flag < gfx::AccessFlagBit::PRESENT || flag == gfx::AccessFlagBit::SHADING_RATE; + return static_cast(flag) < static_cast(gfx::AccessFlagBit::PRESENT) || flag == gfx::AccessFlagBit::SHADING_RATE; +} + +bool accessDependent(const gfx::AccessFlagBit lhs, const gfx::AccessFlagBit &rhs, bool buffer) { + bool dep{false}; + if (buffer) { + dep = !isReadOnlyAccess(lhs) || !isReadOnlyAccess(rhs); + } else { + dep = (!isReadOnlyAccess(lhs) || !isReadOnlyAccess(rhs)) || (lhs != rhs); + } + return dep; } -bool isTransitionStatusDependent(const AccessStatus &lhs, const AccessStatus &rhs); template bool tryAddEdge(uint32_t srcVertex, uint32_t dstVertex, Graph &graph); @@ -249,2362 +417,1961 @@ inline RelationGraph::vertex_descriptor add_vertex(RelationGraph &g) { // NOLINT return add_vertex(g, count++); } -// status of resource access -void buildAccessGraph(const Graphs &graphs) { - // what we need: - // - pass dependency - // - pass attachment access - // AccessTable accessRecord; +bool isResourceView(const ResourceGraph::vertex_descriptor v, const ResourceGraph &resg) { + return resg.isTextureView(v); // || isBufferView +} - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - size_t numPasses = 0; - numPasses += renderGraph.rasterPasses.size(); - numPasses += renderGraph.computePasses.size(); - numPasses += renderGraph.copyPasses.size(); - numPasses += renderGraph.movePasses.size(); - numPasses += renderGraph.raytracePasses.size(); +ResourceRange getResourceRange(const ResourceGraph::vertex_descriptor v, + const ResourceGraph &resg) { + const auto &desc = get(ResourceGraph::DescTag{}, resg, v); + ResourceRange range{ + desc.width, + desc.height, + desc.depthOrArraySize, + }; - resourceAccessGraph.reserve(static_cast(numPasses)); - resourceAccessGraph.resourceNames.reserve(128); - resourceAccessGraph.resourceIndex.reserve(128); + if (isResourceView(v, resg)) { + const auto *const subResView = get_if(v, &resg); + range.firstSlice = subResView->firstArraySlice; + range.numSlices = subResView->numArraySlices; + range.mipLevel = subResView->indexOrFirstMipLevel; + range.levelCount = subResView->numMipLevels; + range.basePlane = subResView->firstPlane; + range.planeCount = subResView->numPlanes; + } else { + range.numSlices = desc.depthOrArraySize; + range.levelCount = desc.mipLevels; + } - resourceAccessGraph.topologicalOrder.reserve(numPasses); - resourceAccessGraph.topologicalOrder.clear(); - resourceAccessGraph.resourceLifeRecord.reserve(resourceGraph.names.size()); + return range; +} - if (!resourceAccessGraph.resourceLifeRecord.empty()) { - resourceAccessGraph.resourceLifeRecord.clear(); +ResourceGraph::vertex_descriptor realID(const ccstd::pmr::string &name, const ResourceGraph &resg) { + auto resID = vertex(name, resg); + while (parent(resID, resg) != ResourceGraph::null_vertex()) { + resID = parent(resID, resg); } + return resID; +} - if (!resourceAccessGraph.leafPasses.empty()) { - resourceAccessGraph.leafPasses.clear(); - } - if (!resourceAccessGraph.culledPasses.empty()) { - resourceAccessGraph.culledPasses.clear(); - } +bool depthStencil(gfx::Format format) { + return format == gfx::Format::DEPTH_STENCIL || format == gfx::Format::DEPTH; +} - // const auto &names = get(RenderGraph::Name, renderGraph); - for (size_t i = 1; i <= numPasses; ++i) { - resourceAccessGraph.leafPasses.emplace(i, LeafStatus{false, true}); +void subResourceFeedback(ResourceGraph &resg, ResourceGraph::vertex_descriptor parentID, gfx::Format subFormat) { + auto &parentDesc = get(ResourceGraph::DescTag{}, resg, parentID); + if (depthStencil(subFormat) || parentDesc.format != subFormat) { + parentDesc.textureFlags |= gfx::TextureFlagBit::MUTABLE_VIEW_FORMAT; } +} - auto startID = add_vertex(resourceAccessGraph, INVALID_ID - 1); - CC_EXPECTS(startID == EXPECT_START_ID); - - add_vertex(relationGraph, startID); +auto dependencyCheck(ResourceAccessGraph &rag, ResourceAccessGraph::vertex_descriptor curVertID, ResourceGraph &resourceGraph, const ViewStatus &viewStatus) { + auto &accessRecord = rag.resourceAccess; + const auto &[name, access, visibility, accessFlag, originRange] = viewStatus; + auto resourceID = rag.resourceIndex.at(name); + const auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resourceID); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resourceID); - for (const auto passID : makeRange(vertices(renderGraph))) { - visitObject( - passID, renderGraph, - [&](const RasterPass &pass) { - processRasterPass(graphs, passID, pass); - }, - [&](const RasterSubpass &pass) { - processRasterSubpass(graphs, passID, pass); - }, - [&](const ComputeSubpass &pass) { - processComputeSubpass(graphs, passID, pass); - }, - [&](const ComputePass &pass) { - processComputePass(graphs, passID, pass); - }, - [&](const CopyPass &pass) { - processCopyPass(graphs, passID, pass); - }, - [&](const RaytracePass &pass) { - processRaytracePass(graphs, passID, pass); - }, - [&](const auto & /*pass*/) { - // do nothing - }); + auto range = originRange; + if (rag.movedSourceStatus.find(name) != rag.movedSourceStatus.end()) { + range = rag.movedSourceStatus.at(name).range; } - auto &rag = resourceAccessGraph; - auto branchCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) -> void { - CC_EXPECTS(out_degree(vertex, rag) == 0); - using FuncType = void (*)(ResourceAccessGraph::vertex_descriptor, ResourceAccessGraph &); - static FuncType leafCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) { - rag.culledPasses.emplace(vertex); - auto &attachments = get(ResourceAccessGraph::AccessNodeTag{}, rag, vertex); - attachments.attachmentStatus.clear(); - if (attachments.nextSubpass) { - delete attachments.nextSubpass; - attachments.nextSubpass = nullptr; - } - auto inEdges = in_edges(vertex, rag); - for (auto iter = inEdges.first; iter < inEdges.second;) { - auto inEdge = *iter; - auto srcVert = source(inEdge, rag); - remove_edge(inEdge, rag); - if (out_degree(srcVert, rag) == 0) { - leafCulling(srcVert, rag); - } - inEdges = in_edges(vertex, rag); - iter = inEdges.first; - } - }; - leafCulling(vertex, rag); - }; + bool isExternalPass = get(get(ResourceGraph::TraitsTag{}, resourceGraph), resourceID).hasSideEffects(); + auto iter = accessRecord.find(name); + ResourceAccessGraph::vertex_descriptor lastVertID{EXPECT_START_ID}; + gfx::AccessFlagBit lastAccess{gfx::AccessFlagBit::NONE}; - // no present pass found, add a fake node to gather leaf node(s). - if (resourceAccessGraph.presentPassID == 0xFFFFFFFF) { - auto ragEndNode = add_vertex(rag, RenderGraph::null_vertex()); - auto rlgEndNode = add_vertex(relationGraph, ragEndNode); - // keep sync before pass reorder done. - CC_EXPECTS(ragEndNode == rlgEndNode); - resourceAccessGraph.presentPassID = ragEndNode; - auto iter = resourceAccessGraph.leafPasses.find(ragEndNode); - constexpr bool isExternal = true; - constexpr bool needCulling = false; - if (iter == resourceAccessGraph.leafPasses.end()) { - resourceAccessGraph.leafPasses.emplace(ragEndNode, LeafStatus{isExternal, needCulling}); + if (iter == accessRecord.end()) { + accessRecord[name].emplace(curVertID, AccessStatus{accessFlag, range}); + if (isExternalPass) { + rag.leafPasses[curVertID] = LeafStatus{true, isReadOnlyAccess(accessFlag)}; + lastAccess = states.states; + } + + // update parent + auto parentID = realID(name, resourceGraph); + if (parentID != resourceID) { + const auto &realName = get(ResourceGraph::NameTag{}, resourceGraph, parentID); + auto lastIter = accessRecord[realName].rbegin(); + if (lastIter->first == curVertID) { + // in case more than 1 view of same resource in a renderpass + ++lastIter; + } + accessRecord[name].emplace(*lastIter); + accessRecord[realName][curVertID] = AccessStatus{accessFlag, range}; + subResourceFeedback(resourceGraph, parentID, desc.format); } else { - resourceAccessGraph.leafPasses.at(ragEndNode) = LeafStatus{isExternal, needCulling}; + accessRecord[name].emplace(0, AccessStatus{lastAccess, range}); } - } + } else { + auto &transMap = iter->second; + CC_ASSERT(!transMap.empty()); - // make leaf node closed walk for pass reorder - for (auto pass : resourceAccessGraph.leafPasses) { - bool isExternal = pass.second.isExternal; - bool needCulling = pass.second.needCulling; + const auto lastRecordIter = (--transMap.end()); + const auto &lastStatus = lastRecordIter->second; + lastAccess = lastStatus.accessFlag; + bool isBuffer = desc.dimension == ResourceDimension::BUFFER; + bool dependent = accessDependent(lastAccess, accessFlag, isBuffer); - if (pass.first != resourceAccessGraph.presentPassID) { - if (isExternal && !needCulling) { - add_edge(pass.first, resourceAccessGraph.presentPassID, resourceAccessGraph); - } else { - // write into transient resources, culled - if constexpr (ENABLE_BRANCH_CULLING) { - branchCulling(pass.first, resourceAccessGraph); + if (!dependent) { + for (auto recordIter = transMap.rbegin(); recordIter != transMap.rend(); ++recordIter) { + if (accessDependent(recordIter->second.accessFlag, accessFlag, isBuffer)) { + lastVertID = recordIter->first; + break; } } - } - } - for (auto rit = resourceAccessGraph.culledPasses.rbegin(); rit != resourceAccessGraph.culledPasses.rend(); ++rit) { - // remove culled vertices, std::less make this set ascending order, so reverse iterate - remove_vertex(*rit, relationGraph); - } - - for (auto rlgVert : makeRange(vertices(relationGraph))) { - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); - rag.topologicalOrder.emplace_back(ragVert); - } -} + if (isExternalPass) { + // only external res will be manually record here, leaf pass with transient resource will be culled by default, + // those leaf passes with ALL read access on external(or with transients) res can be culled. + rag.leafPasses[curVertID].needCulling &= (access == AccessType::READ); + lastAccess = states.states; + } + transMap[curVertID] = {accessFlag, range}; + } else { + lastVertID = lastRecordIter->first; + transMap[curVertID] = {accessFlag, range}; -#pragma region BUILD_BARRIERS -struct BarrierVisitor : public boost::bfs_visitor<> { - using Vertex = ResourceAccessGraph::vertex_descriptor; - using Edge = ResourceAccessGraph::edge_descriptor; - using Graph = ResourceAccessGraph; - - explicit BarrierVisitor( - const ResourceGraph &rg, - BarrierMap &barriers, // what we get - ExternalResMap &extMap, // record external res between frames - ResourceNames &resourceNamesIn, // for resource record - const AccessTable &accessRecordIn, // resource last meet - ResourceLifeRecordMap &rescLifeRecord, // resource lifetime - PmrFlatMap &rpInfosIn) - : barrierMap(barriers), resourceGraph(rg), externalMap(extMap), resourceNames(resourceNamesIn), accessRecord(accessRecordIn), resourceLifeRecord(rescLifeRecord), rpInfos(rpInfosIn) {} - - void updateResourceLifeTime(const ResourceAccessNode &node, ResourceAccessGraph::vertex_descriptor u) { - for (const auto &access : node.attachmentStatus) { - auto name = get(ResourceGraph::NameTag{}, resourceGraph, access.vertID); - if (resourceLifeRecord.find(name) == resourceLifeRecord.end()) { - resourceLifeRecord.emplace(name, ResourceLifeRecord{u, u}); - } else { - resourceLifeRecord.at(name).end = u; + if (rag.leafPasses.find(curVertID) != rag.leafPasses.end()) { + // only write into externalRes counts + if (isExternalPass) { + rag.leafPasses[curVertID].needCulling &= (access == AccessType::READ); + } } } - } - - struct AccessNodeInfo { - const std::vector &status; - std::vector &edgeBarriers; // need to barrier front or back - const Vertex &vertID; - uint32_t subpassIndex{INVALID_ID}; - }; - void processVertex(Vertex u, const Graph &g) { - if (in_degree(u, g) == 0 && out_degree(u, g) == 0) { - // culled - return; + if (rag.leafPasses.find(lastVertID) != rag.leafPasses.end()) { + rag.leafPasses.erase(lastVertID); } - - const ResourceAccessNode &access = get(ResourceAccessGraph::AccessNodeTag{}, g, u); - updateResourceLifeTime(access, u); - - if (barrierMap.find(u) == barrierMap.end()) { - barrierMap.emplace(u, BarrierNode{{}, {}}); + + if(viewStatus.access != AccessType::WRITE) { + subResourceFeedback(resourceGraph, resourceID, desc.format); } + } + auto lastDependentVert = lastVertID; // last dependent vert, WAW/WAR/RAW + auto nearestAccess = lastAccess; // last access, maybe RAR + return std::make_tuple(lastDependentVert, nearestAccess); +} - const auto *srcAccess = &access; - - auto *dstAccess = access.nextSubpass; - auto &blockBarrier = barrierMap[u].blockBarrier; - auto &barriers = barrierMap[u].subpassBarriers; - - uint32_t srcSubpass = 0; - uint32_t dstSubpass = 1; - bool isAdjacent = true; // subpass always adjacent to each other - if (dstAccess) { - if (!dstAccess->nextSubpass) { - return; - } - // subpass at least two passes inside. - // the very first pass becomes attachment status collection of all subpass - CC_ASSERT(dstAccess->nextSubpass); - srcAccess = dstAccess; - dstAccess = dstAccess->nextSubpass; - } - while (srcAccess) { - while (dstAccess) { - // 2 barriers at least when subpass exist - std::vector &srcRearBarriers = barriers[srcSubpass].rearBarriers; - std::vector &dstFrontBarriers = barriers[dstSubpass].frontBarriers; - - AccessNodeInfo from = {srcAccess->attachmentStatus, srcRearBarriers, u, srcSubpass}; - AccessNodeInfo to = {dstAccess->attachmentStatus, dstFrontBarriers, u, dstSubpass}; - std::set noUseSet; - fillBarrier(from, to, isAdjacent, noUseSet); - - dstAccess = dstAccess->nextSubpass; - ++dstSubpass; - } - srcAccess = srcAccess->nextSubpass; - if (srcAccess) { - dstAccess = srcAccess->nextSubpass; - ++srcSubpass; - dstSubpass = srcSubpass + 1; - } +ResourceGraph::vertex_descriptor parentResource(ResourceGraph::vertex_descriptor vert, const ResourceGraph &resg) { + const auto &desc = get(ResourceGraph::DescTag{}, resg, vert); + auto ret = vert; + if (desc.dimension == ResourceDimension::BUFFER) { + // TODO(Zeqaing): bufferview + } else { + auto srcParentID = vert; + while (resg.isTextureView(srcParentID)) { + srcParentID = parent(srcParentID, resg); } + ret = srcParentID; } + return ret; +} - void discover_vertex(Vertex u, const Graph &g) { - processVertex(u, g); - } - - void finish_vertex(Vertex u, const Graph &g) { - auto &rearBarriers = barrierMap[u].blockBarrier.rearBarriers; - auto &frontBarriers = barrierMap[u].blockBarrier.frontBarriers; - Barrier *lastSubpassBarrier = nullptr; - uint32_t subpassIdx{0}; - for (const auto &barriers : barrierMap[u].subpassBarriers) { - if (!barriers.frontBarriers.empty()) { - auto &subpassDependencies = rpInfos.at(u).rpInfo.dependencies; - auto dependency = gfx::SubpassDependency{}; - dependency.srcSubpass = INVALID_ID; - dependency.dstSubpass = subpassIdx; - for (const auto &barrier : barriers.frontBarriers) { - if (barrier.beginStatus.accessFlag == gfx::AccessFlagBit::NONE) { - continue; - } - auto resID = barrier.resourceID; - auto findBarrierByResID = [resID](const Barrier &barrier) { - return barrier.resourceID == resID; - }; - auto resFinalPassID = accessRecord.at(resID).currStatus.vertID; - auto firstMeetIter = std::find_if(frontBarriers.begin(), frontBarriers.end(), findBarrierByResID); - auto innerResIter = std::find_if(rearBarriers.begin(), rearBarriers.end(), findBarrierByResID); - - if (firstMeetIter == frontBarriers.end() && innerResIter == rearBarriers.end() && resFinalPassID >= u) { - auto &collect = frontBarriers.emplace_back(barrier); - collect.beginStatus.vertID = collect.endStatus.vertID = u; - } - if ((barrier.beginStatus.vertID > dependency.srcSubpass) && (barrier.beginStatus.vertID != INVALID_ID)) { - dependency.srcSubpass = barrier.beginStatus.vertID; - } - - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - if (desc.format == gfx::Format::DEPTH_STENCIL || desc.format == gfx::Format::DEPTH) { - if (g.access.at(u).attachmentStatus.size() > 1) { - auto &dsDep = subpassDependencies.emplace_back(); - dsDep.srcSubpass = dependency.srcSubpass; - dsDep.dstSubpass = dependency.dstSubpass; - dsDep.prevAccesses |= barrier.beginStatus.accessFlag; - dsDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - bool isWriteAccess = !isReadOnlyAccess(barrier.endStatus.accessFlag); - if (isWriteAccess) { - auto &dep = subpassDependencies.emplace_back(); - dep.srcSubpass = dependency.srcSubpass; - dep.dstSubpass = dependency.dstSubpass; - dep.prevAccesses |= barrier.beginStatus.accessFlag; - dep.nextAccesses |= barrier.endStatus.accessFlag; - if (hasReadAccess(barrier.endStatus.accessFlag)) { - auto &selfDep = subpassDependencies.emplace_back(); - selfDep.srcSubpass = dependency.dstSubpass; - selfDep.dstSubpass = dependency.dstSubpass; - selfDep.prevAccesses |= barrier.endStatus.accessFlag; - selfDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - dependency.prevAccesses |= barrier.beginStatus.accessFlag; - dependency.nextAccesses |= barrier.endStatus.accessFlag; - } - } - } - if (dependency.prevAccesses != gfx::AccessFlagBit::NONE) { - subpassDependencies.emplace_back(dependency); - } - } - - if (!barriers.rearBarriers.empty()) { - auto &subpassDependencies = rpInfos.at(u).rpInfo.dependencies; - auto dependency = gfx::SubpassDependency{}; - dependency.srcSubpass = subpassIdx; - dependency.dstSubpass = INVALID_ID; - for (const auto &barrier : barriers.rearBarriers) { - if (barrier.endStatus.vertID < dependency.dstSubpass) { - dependency.dstSubpass = barrier.endStatus.vertID; - } +gfx::ShaderStageFlagBit getVisibility(const RenderGraph &renderGraph, const LayoutGraphData &lgd, uint32_t passID, const PmrString &resName) { // NOLINT + auto iter = lgd.attributeIndex.find(resName); + if (iter == lgd.attributeIndex.end()) { + iter = lgd.constantIndex.find(resName); + if (iter == lgd.constantIndex.end()) { + // resource not in descriptor: eg. input or output attachment. + return gfx::ShaderStageFlagBit::NONE; + } + } + auto slotID = iter->second; - auto resID = barrier.resourceID; - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - if (desc.format == gfx::Format::DEPTH_STENCIL || desc.format == gfx::Format::DEPTH) { - if (g.access.at(u).attachmentStatus.size() > 1) { - auto &dsDep = subpassDependencies.emplace_back(); - dsDep.srcSubpass = dependency.srcSubpass; - dsDep.dstSubpass = dependency.dstSubpass; - dsDep.prevAccesses |= barrier.beginStatus.accessFlag; - dsDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - bool isWriteAccess = !isReadOnlyAccess(barrier.endStatus.accessFlag); - if (isWriteAccess) { - auto &dep = subpassDependencies.emplace_back(); - dep.srcSubpass = dependency.srcSubpass; - dep.dstSubpass = dependency.dstSubpass; - dep.prevAccesses |= barrier.beginStatus.accessFlag; - dep.nextAccesses |= barrier.endStatus.accessFlag; - if (hasReadAccess(barrier.endStatus.accessFlag)) { - auto &selfDep = subpassDependencies.emplace_back(); - selfDep.srcSubpass = dependency.dstSubpass; - selfDep.dstSubpass = dependency.dstSubpass; - selfDep.prevAccesses |= barrier.endStatus.accessFlag; - selfDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - dependency.prevAccesses |= barrier.beginStatus.accessFlag; - dependency.nextAccesses |= barrier.endStatus.accessFlag; - } - } - } - if (dependency.prevAccesses != gfx::AccessFlagBit::NONE) { - subpassDependencies.emplace_back(dependency); + auto layoutName = get(RenderGraph::LayoutTag{}, renderGraph, passID); + auto layoutID = locate(LayoutGraphData::null_vertex(), layoutName, lgd); + const auto &layout = get(LayoutGraphData::LayoutTag{}, lgd, layoutID); + for (const auto &pair : layout.descriptorSets) { + for (const auto &block : pair.second.descriptorSetLayoutData.descriptorBlocks) { + for (const auto &descriptor : block.descriptors) { + if (descriptor.descriptorID.value == slotID.value) { + return block.visibility; } } - ++subpassIdx; } } + // unreachable + CC_EXPECTS(false); - void fillBarrier(const AccessNodeInfo &from, const AccessNodeInfo &to, bool isAdjacent, std::set &subpassResourceSet) { - const auto &[srcStatus, srcRearBarriers, srcPassVert, srcHasSubpass] = from; - const auto &[dstStatus, dstFrontBarriers, dstPassVert, dstHasSubpass] = to; - auto srcVert = srcPassVert; - auto dstVert = dstPassVert; - bool subToSubDeps = false; - if (srcPassVert == dstPassVert) { - srcVert = srcHasSubpass; - dstVert = dstHasSubpass; - subToSubDeps = true; - } - - bool dstExternalDeps = (srcHasSubpass != INVALID_ID) && (dstHasSubpass == INVALID_ID); - bool srcExternalDeps = (srcHasSubpass == INVALID_ID) && (dstHasSubpass != INVALID_ID); - - std::vector commonResources; - std::set_intersection(srcStatus.begin(), srcStatus.end(), - dstStatus.begin(), dstStatus.end(), - std::back_inserter(commonResources), - [](const AccessStatus &lhs, const AccessStatus &rhs) { - return lhs.vertID < rhs.vertID; - }); - if (!commonResources.empty()) { - // this edge is a logic edge added during pass reorder, - // no real dependency between this two vertices. - - // NOLINTNEXTLINE - for (uint32_t i = 0; i < commonResources.size(); ++i) { - uint32_t resourceID = commonResources[i].vertID; - if (subpassResourceSet.find(resourceID) != subpassResourceSet.end()) { - continue; - } - subpassResourceSet.emplace(resourceID); - auto findAccessByID = [resourceID](const AccessStatus &resAccess) { return resAccess.vertID == resourceID; }; - auto fromIter = std::find_if(srcStatus.begin(), srcStatus.end(), findAccessByID); - auto toIter = std::find_if(dstStatus.begin(), dstStatus.end(), findAccessByID); + return gfx::ShaderStageFlagBit::NONE; +}; - // can't happen - CC_ASSERT(fromIter != srcStatus.end()); - CC_ASSERT(toIter != dstStatus.end()); +gfx::MemoryAccessBit toGfxAccess(AccessType type) { + switch (type) { + case AccessType::READ: + return gfx::MemoryAccessBit::READ_ONLY; + case AccessType::WRITE: + return gfx::MemoryAccessBit::WRITE_ONLY; + case AccessType::READ_WRITE: + return gfx::MemoryAccessBit::READ_WRITE; + default: + return gfx::MemoryAccessBit::NONE; + } +}; - if (!isTransitionStatusDependent(*fromIter, *toIter)) { - continue; - } - - auto findBarrierNodeByResID = [resourceID](const Barrier &barrier) { return resourceID == barrier.resourceID; }; +auto mapTextureFlags(ResourceFlags flags) { + gfx::TextureUsage usage = gfx::TextureUsage::NONE; + if ((flags & ResourceFlags::SAMPLED) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::SAMPLED; + } + if ((flags & ResourceFlags::STORAGE) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::STORAGE; + } + if ((flags & ResourceFlags::SHADING_RATE) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::SHADING_RATE; + } + if ((flags & ResourceFlags::COLOR_ATTACHMENT) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::COLOR_ATTACHMENT; + } + if ((flags & ResourceFlags::DEPTH_STENCIL_ATTACHMENT) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT; + } + if ((flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::INPUT_ATTACHMENT; + } + return usage; +} - auto srcBarrierIter = srcRearBarriers.empty() ? srcRearBarriers.end() : std::find_if(srcRearBarriers.begin(), srcRearBarriers.end(), findBarrierNodeByResID); - auto dstBarrierIter = dstFrontBarriers.empty() ? dstFrontBarriers.end() : std::find_if(dstFrontBarriers.begin(), dstFrontBarriers.end(), findBarrierNodeByResID); +auto getTextureStatus(std::string_view name, AccessType access, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph, bool rasterized) { + gfx::ShaderStageFlags vis{visibility}; + if (vis == gfx::ShaderStageFlags::NONE) { + // attachment + vis = gfx::ShaderStageFlagBit::FRAGMENT; + } + gfx::AccessFlags accesFlag; + auto vertex = resourceGraph.valueIndex.at(name.data()); - auto dstVertDistribute = [&](uint32_t &vertID, bool depends) { - if (depends) { - vertID = INVALID_ID; - } else if (subToSubDeps) { - vertID = dstVert; - } else { - vertID = isAdjacent ? srcVert : dstVert; - } - }; - if (srcBarrierIter == srcRearBarriers.end()) { - auto srcAccess = (*fromIter); - srcAccess.vertID = dstExternalDeps ? INVALID_ID : srcVert; - auto dstAccess = (*toIter); - dstVertDistribute(dstAccess.vertID, dstExternalDeps); - - srcRearBarriers.emplace_back(Barrier{ - resourceID, - isAdjacent ? gfx::BarrierType::FULL : gfx::BarrierType::SPLIT_BEGIN, - nullptr, // generate later - srcAccess, - dstAccess, - }); - srcBarrierIter = std::prev(srcRearBarriers.end()); - } else { - if (isAdjacent) { - srcBarrierIter->type = gfx::BarrierType::FULL; - auto srcAccess = (*fromIter); - srcAccess.vertID = dstExternalDeps ? INVALID_ID : srcVert; - srcBarrierIter->beginStatus = srcAccess; - auto dstAccess = (*toIter); - dstVertDistribute(dstAccess.vertID, dstExternalDeps); - srcBarrierIter->endStatus = dstAccess; - } else { - auto &blockBarrier = barrierMap.at(srcPassVert).blockBarrier; - auto lastVert = srcBarrierIter->beginStatus.vertID; - auto blockIter = blockBarrier.rearBarriers.end(); - if (subToSubDeps) { - blockIter = std::find_if(blockBarrier.rearBarriers.begin(), blockBarrier.rearBarriers.end(), findBarrierNodeByResID); - lastVert = blockIter->beginStatus.vertID; - } - if (srcVert >= lastVert) { - auto srcAccess = (*fromIter); - srcAccess.vertID = srcVert; - if (blockIter != blockBarrier.rearBarriers.end()) { - blockIter->beginStatus = srcAccess; - } - - uint32_t siblingPass = lastVert; - if (srcVert > lastVert) { - auto &siblingPassBarrier = barrierMap[siblingPass].blockBarrier.rearBarriers; - auto siblingIter = std::find_if(siblingPassBarrier.begin(), siblingPassBarrier.end(), - [resourceID](const Barrier &barrier) { - return resourceID == barrier.resourceID; - }); - CC_ASSERT(siblingIter != siblingPassBarrier.end()); - siblingPassBarrier.erase(siblingIter); - } - } - } - } + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex); - if (srcBarrierIter->type == gfx::BarrierType::SPLIT_BEGIN) { - auto srcAccess = (*fromIter); - srcAccess.vertID = srcExternalDeps ? INVALID_ID : srcVert; - auto dstAccess = (*toIter); - dstVertDistribute(dstAccess.vertID, dstExternalDeps); - if (dstBarrierIter == dstFrontBarriers.end()) { - // if isAdjacent, full barrier already in src rear barriers. - if (!isAdjacent) { - dstFrontBarriers.emplace_back(Barrier{ - resourceID, - gfx::BarrierType::SPLIT_END, - nullptr, - srcAccess, - dstAccess, - }); - } - } else { - if (isAdjacent) { - // adjacent, barrier should be commit at fromPass, and remove this iter from dstBarriers - srcBarrierIter->type = gfx::BarrierType::FULL; - srcBarrierIter->beginStatus = srcAccess; - srcBarrierIter->endStatus = dstAccess; - dstFrontBarriers.erase(dstBarrierIter); - } else { - // logic but not exec adjacent - // and more adjacent(distance from src) than another pass which hold a use of resourceID - // replace previous one - - // 1 --> 2 --> 3 - // ↓ - // 4 --> 5 --> 6 - - // [if] real pass order: 1 - 2 - 4 - 5 - 3 - 6 - - // 2 and 5 read from ResA, 6 writes to ResA - // 5 and 6 logically adjacent but not adjacent in execution order. - // barrier for ResA between 2 - 6 can be totally replaced by 5 - 6 - auto &blockBarrier = barrierMap.at(dstPassVert).blockBarrier; - auto blockIter = blockBarrier.frontBarriers.end(); - auto lastVert = dstBarrierIter->endStatus.vertID; - if (subToSubDeps) { - blockIter = std::find_if(blockBarrier.frontBarriers.begin(), blockBarrier.frontBarriers.end(), findBarrierNodeByResID); - lastVert = blockIter->endStatus.vertID; - } - if (dstVert <= lastVert) { - uint32_t siblingPass = lastVert; - dstBarrierIter->endStatus = dstAccess; - - // remove the further redundant barrier - auto &siblingPassBarrier = barrierMap[siblingPass].blockBarrier.frontBarriers; - auto siblingIter = std::find_if(siblingPassBarrier.begin(), siblingPassBarrier.end(), - [resourceID](const Barrier &barrier) { - return resourceID == barrier.resourceID; - }); - CC_ASSERT(siblingIter != siblingPassBarrier.end()); - siblingPassBarrier.erase(siblingIter); - } - } - } - } - } + // can't find this resource in layoutdata, should be output attachment. + gfx::TextureUsage texUsage = gfx::TextureUsage::NONE; + if (access != AccessType::WRITE) { + if ((desc.flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE && rasterized) { + texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::INPUT_ATTACHMENT)); + } else { + texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::SAMPLED | gfx::TextureUsage::STORAGE | gfx::TextureUsage::SHADING_RATE | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT)); } + } - //----------------------------------------------check external---------------------------------------------- - auto barrierExternalRes = [&](const AccessStatus &resourcecAccess, Vertex vert) { - uint32_t rescID = resourcecAccess.vertID; - const auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, rescID); - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, rescID); - const PmrString &resName = get(ResourceGraph::NameTag{}, resourceGraph, rescID); - auto resIter = externalMap.find(resName); - if (traits.hasSideEffects()) { - // first meet in this frame - if (resIter == externalMap.end()) { - // first meet in this program - if (states.states == gfx::AccessFlagBit::NONE) { - auto lastRescAccess = AccessStatus{ - vert, - gfx::ShaderStageFlagBit::NONE, - gfx::MemoryAccessBit::NONE, - gfx::PassType::RASTER, - gfx::AccessFlagBit::NONE, - gfx::TextureUsageBit::NONE, - TextureRange{}, - }; - auto currRescAccess = resourcecAccess; - - // resource id in access -> pass id in barrier - currRescAccess.vertID = vert; - - lastRescAccess.accessFlag = gfx::AccessFlagBit::NONE; - - externalMap.insert({resName, - ResourceTransition{ - lastRescAccess, - currRescAccess, - }}); - } else { - externalMap[resName].lastStatus = {}; - externalMap[resName].lastStatus.vertID = INVALID_ID; - externalMap[resName].lastStatus.accessFlag = states.states; - // deprecated - externalMap[resName].lastStatus.usage = gfx::TextureUsageBit::NONE; - externalMap[resName].lastStatus.range = TextureRange{}; - - externalMap[resName].currStatus = resourcecAccess; - externalMap[resName].currStatus.vertID = vert; - - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, rescID); - if (isTransitionStatusDependent(externalMap[resName].lastStatus, externalMap[resName].currStatus)) { - resourceNames.emplace(resName); - } - } - } else { - if (resIter->second.currStatus.vertID < vert) { - //[pass: vert] is later access than in iter. - externalMap[resName].currStatus = resourcecAccess; - externalMap[resName].currStatus.vertID = vert; - if (!isReadOnlyAccess(resourcecAccess.accessFlag)) { - resourceNames.emplace(resName); - } - } - } - } - }; + if (access != AccessType::READ) { + texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::STORAGE)); + } + accesFlag = gfx::getAccessFlags(texUsage, toGfxAccess(access), vis); - for (const AccessStatus &rescAccess : srcStatus) { - barrierExternalRes(rescAccess, from.vertID); - } + return std::make_tuple(vis, accesFlag); +}; - for (const AccessStatus &rescAccess : dstStatus) { - barrierExternalRes(rescAccess, to.vertID); - } - //--------------------------------------------------------------------------------------------------------- +auto getBufferStatus(const PmrString &name, AccessType access, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph) { + gfx::AccessFlags accesFlag; + auto vertex = resourceGraph.valueIndex.at(name); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex); + + gfx::BufferUsage bufferUsage{gfx::BufferUsage::NONE}; + // copy is not included in this logic because copy can be set TRANSFER_xxx directly. + if (access != AccessType::READ) { + bufferUsage = gfx::BufferUsage::STORAGE; } - void examine_edge(Edge e, const Graph &g) { - Vertex from = source(e, g); - Vertex to = target(e, g); + if (access != AccessType::WRITE) { + bool uniformFlag = (desc.flags & ResourceFlags::UNIFORM) != ResourceFlags::NONE; + bool storageFlag = (desc.flags & ResourceFlags::STORAGE) != ResourceFlags::NONE; - // hasSubpass ? fromAccess is a single node with all attachment status stored in 'attachmentStatus' - // : fromAccess is head of chain of subpasses, which stores all attachment status in 'attachmentStatus' - const ResourceAccessNode &fromAccess = get(ResourceAccessGraph::AccessNodeTag{}, g, from); - const ResourceAccessNode &toAccess = get(ResourceAccessGraph::AccessNodeTag{}, g, to); + // CC_EXPECTS(uniformFlag ^ storageFlag); + // uniform or read-only storage buffer + bufferUsage = uniformFlag ? gfx::BufferUsage::UNIFORM : gfx::BufferUsage::STORAGE; + } - bool isAdjacent = isPassExecAdjecent(from, to); - std::vector commonResources; + // those buffers not found in descriptorlayout but appear here, + // can and only can be VERTEX/INDEX/INDIRECT BUFFER, + // only copy pass is allowed. - const auto *srcHead = &fromAccess; - const auto *dstHead = &toAccess; + auto memAccess = toGfxAccess(access); + accesFlag = gfx::getAccessFlags(bufferUsage, gfx::MemoryUsage::DEVICE, memAccess, visibility); + return std::make_tuple(visibility, accesFlag); +}; - bool srcHasSubpass = srcHead->nextSubpass; - bool dstHasSubpass = dstHead->nextSubpass; - srcHead = srcHasSubpass ? srcHead->nextSubpass : srcHead; +void addAccessStatus(ResourceAccessGraph &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status) { + const auto &[name, access, visibility, accessFlag, range] = status; + uint32_t rescID = rg.valueIndex.at(name); + const auto &resourceDesc = get(ResourceGraph::DescTag{}, rg, rescID); + const auto &traits = get(ResourceGraph::TraitsTag{}, rg, rescID); - std::stack reverseSubpassQ; - while (srcHead) { - reverseSubpassQ.push(srcHead); - srcHead = srcHead->nextSubpass; - } - ccstd::set subpassResourceSet; - while (!reverseSubpassQ.empty()) { - uint32_t srcSubpassIndex = reverseSubpassQ.size() - 1; - srcHead = reverseSubpassQ.top(); - reverseSubpassQ.pop(); - const std::vector &fromStatus = srcHead->attachmentStatus; - std::vector &srcRearBarriers = srcHasSubpass ? barrierMap[from].subpassBarriers[srcSubpassIndex].rearBarriers : barrierMap[from].blockBarrier.rearBarriers; - uint32_t dstSubpassIndex = 0; - dstHead = &toAccess; - bool dstHasSubpass = dstHead->nextSubpass; - dstHead = dstHasSubpass ? toAccess.nextSubpass : &toAccess; - while (dstHead) { - const std::vector &toStatus = dstHead->attachmentStatus; - std::vector &dstFrontBarriers = dstHasSubpass ? barrierMap[to].subpassBarriers[dstSubpassIndex].frontBarriers : barrierMap[to].blockBarrier.frontBarriers; - AccessNodeInfo fromInfo = {fromStatus, srcRearBarriers, from, srcHasSubpass ? static_cast(reverseSubpassQ.size()) : INVALID_ID}; - AccessNodeInfo toInfo = {toStatus, dstFrontBarriers, to, dstHasSubpass ? dstSubpassIndex : INVALID_ID}; - bool isExecAdjacent = isAdjacent && (!srcHead->nextSubpass && !dstSubpassIndex); - fillBarrier(fromInfo, toInfo, isAdjacent, subpassResourceSet); - dstHead = dstHead->nextSubpass; - ++dstSubpassIndex; - } - } + CC_EXPECTS(rg.valueIndex.find(name) != rg.valueIndex.end()); + if (std::find(rag.resourceNames.begin(), rag.resourceNames.end(), name) == rag.resourceNames.end()) { + rag.resourceIndex.emplace(name, rescID); + rag.resourceNames.emplace_back(name); + } - auto &rearBarriers = barrierMap[from].blockBarrier.rearBarriers; - auto &frontBarriers = barrierMap[from].blockBarrier.frontBarriers; - - uint32_t subpassIdx = 0; - for (const auto &barriers : barrierMap[from].subpassBarriers) { - for (const auto &barrier : barriers.rearBarriers) { - auto resID = barrier.resourceID; - auto findBarrierByResID = [resID](const Barrier &barrier) { - return barrier.resourceID == resID; - }; - auto iter = std::find_if(rearBarriers.begin(), rearBarriers.end(), findBarrierByResID); - auto resFinalPassID = accessRecord.at(resID).currStatus.vertID; - - if (resFinalPassID > from) { - const auto *dstHead = dstHasSubpass ? toAccess.nextSubpass : &toAccess; - const AccessStatus *dstAccess{nullptr}; - while (dstHead) { - auto iter = std::find_if(dstHead->attachmentStatus.begin(), dstHead->attachmentStatus.end(), [resID](const AccessStatus &access) { - return access.vertID == resID; - }); - if (iter != dstHead->attachmentStatus.end()) { - dstAccess = &(*iter); - break; - } - dstHead = dstHead->nextSubpass; - } + node.resourceStatus.emplace(name, AccessStatus{ + accessFlag, + range, + }); +} - if (!dstAccess) { - continue; - } +namespace { +const uint32_t ATTACHMENT_TYPE_WEIGHT[] = {0, 2, 1}; - const auto *srcHead = srcHasSubpass ? fromAccess.nextSubpass : &fromAccess; - uint32_t step = 0; - while (step <= subpassIdx) { - srcHead = srcHead->nextSubpass; - ++step; - } +struct AttachmentSortKey { + gfx::SampleCount samples; + AccessType accessType; + uint32_t attachmentWeight; + const ccstd::pmr::string name; +}; - bool laterUse = false; - while (srcHead) { - const auto &attachments = srcHead->attachmentStatus; - laterUse |= std::any_of(attachments.begin(), attachments.end(), [resID](const AccessStatus &access) { - return access.vertID == resID; - }); - srcHead = srcHead->nextSubpass; - } +struct AttachmentComparator { + bool operator()(const AttachmentSortKey &lhs, const AttachmentSortKey &rhs) const { + return std::tie(rhs.samples, lhs.accessType, lhs.attachmentWeight, lhs.name) < std::tie(lhs.samples, rhs.accessType, rhs.attachmentWeight, rhs.name); + } +}; - // laterUse: in case it's a split begin/end. - const auto &srcAccess = laterUse ? barrier.endStatus : barrier.beginStatus; - if (isTransitionStatusDependent(srcAccess, *dstAccess)) { - if (iter == rearBarriers.end()) { - auto &collect = rearBarriers.emplace_back(barrier); - collect.beginStatus.vertID = from; - collect.endStatus.vertID = isAdjacent ? from : to; - } else if (iter->endStatus.vertID >= to) { - (*iter) = barrier; - iter->beginStatus.vertID = from; - iter->endStatus.vertID = isAdjacent ? from : to; - } - } +struct ViewInfo { + gfx::Format format{gfx::Format::UNKNOWN}; + LayoutAccess access; + gfx::LoadOp loadOp; + gfx::StoreOp storeOp; + AttachmentType attachmentType; +}; + +using AttachmentMap = ccstd::pmr::map; +} // namespace + +void fillRenderPassInfo(const AttachmentMap &colorMap, + FGRenderPassInfo &fgRenderpassInfo, + const ResourceGraph &resg) { + for (const auto &pair : colorMap) { + const auto &key = pair.first; + const auto &viewInfo = pair.second; + if (viewInfo.attachmentType == AttachmentType::DEPTH_STENCIL) { + // put ds[sample > 1] to ds, ds[sample == 1] to dsResolve, swap them if not a ms pass in endRenderPass. + bool ms = key.samples != gfx::SampleCount::X1; + auto &ds = ms ? fgRenderpassInfo.rpInfo.depthStencilAttachment + : fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; + auto &dsAccess = ms ? fgRenderpassInfo.dsAccess : fgRenderpassInfo.dsResolveAccess; + if (ds.format == gfx::Format::UNKNOWN) { + ds.depthLoadOp = viewInfo.loadOp; + ds.stencilLoadOp = viewInfo.loadOp; + ds.sampleCount = key.samples; + ds.format = viewInfo.format; + dsAccess.prevAccess = viewInfo.access.prevAccess; + } + ds.depthStoreOp = viewInfo.storeOp; + ds.stencilStoreOp = viewInfo.storeOp; + dsAccess.nextAccess = viewInfo.access.nextAccess; + + auto iter = fgRenderpassInfo.viewIndex.find(key.name.c_str()); + if (iter == fgRenderpassInfo.viewIndex.end()) { + auto parentID = realID(key.name, resg); + const auto &parentName = get(ResourceGraph::NameTag{}, resg, parentID); + AttachmentInfo attachmentInfo(fgRenderpassInfo.get_allocator()); + attachmentInfo.parentName = parentName; + attachmentInfo.attachmentIndex = gfx::INVALID_BINDING; + attachmentInfo.isResolveView = fgRenderpassInfo.resolveCount && key.samples == gfx::SampleCount::X1; + fgRenderpassInfo.viewIndex.emplace(key.name, attachmentInfo); + } + } else { + auto iter = fgRenderpassInfo.viewIndex.find(key.name.c_str()); + auto &colors = fgRenderpassInfo.rpInfo.colorAttachments; + if (iter == fgRenderpassInfo.viewIndex.end()) { + auto colorIndex = fgRenderpassInfo.orderedViews.size(); + auto &color = colors.emplace_back(); + color.format = viewInfo.format; + color.sampleCount = key.samples; + color.storeOp = viewInfo.storeOp; + color.loadOp = viewInfo.loadOp; + fgRenderpassInfo.colorAccesses.emplace_back(LayoutAccess{viewInfo.access.prevAccess, viewInfo.access.nextAccess}); + fgRenderpassInfo.colorAccesses[colorIndex].nextAccess = viewInfo.access.nextAccess; + + auto parentID = realID(key.name, resg); + const auto &parentName = get(ResourceGraph::NameTag{}, resg, parentID); + AttachmentInfo attachmentInfo(fgRenderpassInfo.get_allocator()); + attachmentInfo.parentName = parentName; + attachmentInfo.attachmentIndex = static_cast(fgRenderpassInfo.orderedViews.size()); + attachmentInfo.isResolveView = fgRenderpassInfo.resolveCount && key.samples == gfx::SampleCount::X1; + + fgRenderpassInfo.viewIndex.emplace(key.name, attachmentInfo); + fgRenderpassInfo.orderedViews.emplace_back(key.name); + } else { + const auto &attachmentInfo = fgRenderpassInfo.viewIndex.at(key.name); + auto cIndex = attachmentInfo.attachmentIndex; + if (cIndex == gfx::INVALID_BINDING) { + bool ms = key.samples == gfx::SampleCount::X1; + auto &ds = ms ? fgRenderpassInfo.rpInfo.depthStencilAttachment : fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; + ds.depthStoreOp = viewInfo.storeOp; + ds.stencilStoreOp = viewInfo.storeOp; + auto &access = ms ? fgRenderpassInfo.dsAccess : fgRenderpassInfo.dsResolveAccess; + access.nextAccess = viewInfo.access.nextAccess; + } else { + auto &color = fgRenderpassInfo.rpInfo.colorAttachments[cIndex]; + color.storeOp = viewInfo.storeOp; + fgRenderpassInfo.colorAccesses[cIndex].nextAccess = viewInfo.access.nextAccess; } } + } + } +}; - for (const auto &barrier : barriers.frontBarriers) { - auto resID = barrier.resourceID; - auto findBarrierByResID = [resID](const Barrier &barrier) { - return barrier.resourceID == resID; - }; - auto resFinalPassID = accessRecord.at(resID).currStatus.vertID; - auto firstMeetIter = std::find_if(frontBarriers.begin(), frontBarriers.end(), findBarrierByResID); - auto innerResIter = std::find_if(rearBarriers.begin(), rearBarriers.end(), findBarrierByResID); - - if (firstMeetIter == frontBarriers.end() && innerResIter == rearBarriers.end() && resFinalPassID > from) { - frontBarriers.emplace_back(barrier); - } +void extractNames(const ccstd::pmr::string &resName, + const RasterView &view, + ccstd::pmr::vector> &names) { + // depth_stencil + if (view.attachmentType == AttachmentType::DEPTH_STENCIL) { + if (!defaultAttachment(view.slotName)) { + if (strstr(resName.c_str(), "/depth")) { + names.emplace_back(resName, 0); + } else { + names.emplace_back(resName + "/depth", 0); + } + } + if (!defaultAttachment(view.slotName1)) { + if (strstr(resName.c_str(), "/stencil")) { + names.emplace_back(resName, 1); + } else { + names.emplace_back(resName + "/stencil", 1); } } - subpassIdx++; } - const AccessTable &accessRecord; - BarrierMap &barrierMap; - const ResourceGraph &resourceGraph; - ExternalResMap &externalMap; // last frame to curr frame status transition - ResourceNames &resourceNames; // record those which been written - ResourceLifeRecordMap &resourceLifeRecord; - PmrFlatMap &rpInfos; -}; + if (names.empty()) { + names.emplace_back(resName, 0); + } + // cube -void buildBarriers(FrameGraphDispatcher &fgDispatcher) { - auto *scratch = fgDispatcher.scratch; - const auto &renderGraph = fgDispatcher.graph; - const auto &layoutGraph = fgDispatcher.layoutGraph; - auto &resourceGraph = fgDispatcher.resourceGraph; - auto &relationGraph = fgDispatcher.relationGraph; - auto &externalResMap = fgDispatcher.externalResMap; - auto &rag = fgDispatcher.resourceAccessGraph; + // array +} - // record resource current in-access and out-access for every single node - if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, resourceGraph, layoutGraph, rag, relationGraph}; - buildAccessGraph(graphs); - fgDispatcher._accessGraphBuilt = true; +auto checkRasterViews(const Graphs &graphs, + ResourceAccessGraph::vertex_descriptor ragVertID, + ResourceAccessNode &node, + const RasterViewsMap &rasterViews, + AttachmentMap &colorMap) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + const auto passID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, ragVertID); + bool dependent = false; + bool hasDS = false; + + auto explicitVis = gfx::ShaderStageFlagBit::NONE; + if (holds(passID, renderGraph)) { + explicitVis |= gfx::ShaderStageFlagBit::COMPUTE; } - // found pass id in this map ? barriers you should commit when run into this pass - // : or no extra barrier needed. - BarrierMap &batchedBarriers = fgDispatcher.barrierMap; + for (const auto &pair : rasterViews) { + const auto &rasterView = pair.second; + const auto &resName = pair.first; + ccstd::pmr::vector> names(resourceAccessGraph.get_allocator()); + const auto resID = vertex(resName, resourceGraph); + auto access = rasterView.accessType; + gfx::ShaderStageFlagBit originVis = getVisibility(renderGraph, layoutGraphData, passID, pair.second.slotName) | explicitVis | pair.second.shaderStageFlags; + const auto &[vis, accessFlag] = getTextureStatus(resName.data(), access, originVis, resourceGraph, true); + auto range = getResourceRange(resID, resourceGraph); + + ViewStatus viewStatus{resName, access, vis, accessFlag, range}; + addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - { - // barrier first meet - // O(N) actually - ccstd::set firstMeet; - for (size_t i = 0; i < rag.access.size(); ++i) { - const auto *status = &rag.access[i]; - for (const auto &attachment : status->attachmentStatus) { - AccessStatus lastStatus{ - static_cast(i), - gfx::ShaderStageFlagBit::NONE, - gfx::MemoryAccessBit::NONE, - gfx::PassType::RASTER, - gfx::AccessFlagBit::NONE, - gfx::TextureUsageBit::NONE, - TextureRange{}, - }; - - AccessStatus currStatus = attachment; - currStatus.vertID = static_cast(i); - - gfx::BarrierType bType = gfx::BarrierType::FULL; - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, attachment.vertID); - if (traits.hasSideEffects()) { - const auto &accessFlag = get(ResourceGraph::StatesTag{}, resourceGraph, attachment.vertID).states; - if (accessFlag != gfx::AccessFlagBit::NONE) { - lastStatus.accessFlag = accessFlag; - bType = traits.residency == ResourceResidency::BACKBUFFER ? gfx::BarrierType::FULL : gfx::BarrierType::SPLIT_END; - } - if (!isTransitionStatusDependent(lastStatus, currStatus)) { - continue; - } - } - if (firstMeet.find(attachment.vertID) == firstMeet.end()) { - firstMeet.emplace(attachment.vertID); - - if (batchedBarriers.find(i) == batchedBarriers.end()) { - batchedBarriers.emplace(i, BarrierNode{}); - auto &rpInfo = rag.rpInfos[i].rpInfo; - // NOLINTNEXTLINE (readability-container-size-empty) - if (rpInfo.subpasses.size() >= 1) { - batchedBarriers[i].subpassBarriers.resize(rpInfo.subpasses.size()); - } - } + const auto &[lastVertId, lastAccess] = dependencyCheck(resourceAccessGraph, ragVertID, resourceGraph, viewStatus); + tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); + tryAddEdge(lastVertId, ragVertID, relationGraph); + dependent |= (lastVertId != EXPECT_START_ID); + + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + colorMap.emplace(AttachmentSortKey{desc.sampleCount, + rasterView.accessType, + ATTACHMENT_TYPE_WEIGHT[static_cast(rasterView.attachmentType)], + resName}, + ViewInfo{desc.format, + LayoutAccess{lastAccess, accessFlag}, + rasterView.loadOp, + rasterView.storeOp, + rasterView.attachmentType}); + hasDS |= rasterView.attachmentType == AttachmentType::DEPTH_STENCIL; + } + return std::make_tuple(dependent, hasDS); +} - auto &blockFrontBarrier = batchedBarriers.at(i).blockBarrier.frontBarriers; - auto resIter = std::find_if(blockFrontBarrier.begin(), blockFrontBarrier.end(), [&attachment](const Barrier &barrier) { return barrier.resourceID == attachment.vertID; }); - if (resIter == blockFrontBarrier.end()) { - Barrier firstMeetBarrier{ - attachment.vertID, - bType, - nullptr, - lastStatus, - currStatus, - }; - blockFrontBarrier.emplace_back(firstMeetBarrier); - } - auto *nextStatus = status->nextSubpass; - uint32_t index = 0; - while (nextStatus) { - const auto &subpassStatus = nextStatus->attachmentStatus; - auto &subpassBarriers = batchedBarriers.at(i).subpassBarriers; - auto &frontBarriers = subpassBarriers[index].frontBarriers; - auto iter = std::find_if(subpassStatus.begin(), subpassStatus.end(), [&attachment](const AccessStatus &access) { return access.vertID == attachment.vertID; }); - if (iter != subpassStatus.end()) { - lastStatus.vertID = 0xFFFFFFFF; - currStatus.vertID = index; - currStatus.accessFlag = iter->accessFlag; - Barrier firstMeetBarrier{ - attachment.vertID, - bType, - nullptr, - lastStatus, - currStatus, - }; - frontBarriers.emplace_back(firstMeetBarrier); - break; - } - nextStatus = nextStatus->nextSubpass; - index++; - } - } +bool checkComputeViews(const Graphs &graphs, ResourceAccessGraph::vertex_descriptor ragVertID, ResourceAccessNode &node, const ComputeViewsMap &computeViews) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + const auto passID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, ragVertID); + bool dependent = false; + + for (const auto &pair : computeViews) { + const auto &values = pair.second; + const auto &resName = pair.first; + const auto resID = vertex(resName, resourceGraph); + auto range = getResourceRange(vertex(resName, resourceGraph), resourceGraph); + for (const auto &computeView : values) { + gfx::ShaderStageFlagBit vis = gfx::ShaderStageFlagBit::NONE; + for (const auto &view : pair.second) { + vis |= getVisibility(renderGraph, layoutGraphData, passID, view.name); + vis |= view.shaderStageFlags; + } + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; + if (desc.dimension == ResourceDimension::BUFFER) { + const auto &[ignore0, access] = getBufferStatus(pair.first, computeView.accessType, vis, resourceGraph); + accessFlag = access; + } else { + const auto &[ignore0, access] = getTextureStatus(pair.first, computeView.accessType, vis, resourceGraph, false); + accessFlag = access; } + range.firstSlice = computeView.plane; + range.numSlices = 1; + ViewStatus viewStatus{pair.first, computeView.accessType, vis, accessFlag, range}; + addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); + auto [lastVertId, neareastAccess] = dependencyCheck(resourceAccessGraph, ragVertID, resourceGraph, viewStatus); + + tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); + tryAddEdge(lastVertId, ragVertID, relationGraph); + dependent = lastVertId != EXPECT_START_ID; } } - ResourceNames namesSet; - { - // barrier between passes - BarrierVisitor visitor(resourceGraph, batchedBarriers, externalResMap, namesSet, rag.accessRecord, rag.resourceLifeRecord, rag.rpInfos); - auto colors = rag.colors(scratch); - boost::queue q; - - boost::breadth_first_visit( - rag, - EXPECT_START_ID, - q, - visitor, - get(colors, rag)); - } - - // external res barrier for next frame - for (const auto &externalPair : externalResMap) { - const auto &resName = externalPair.first; - const auto &transition = externalPair.second; - auto resID = resourceGraph.valueIndex.at(resName); - const auto &resTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, resID); - auto &rescStates = get(ResourceGraph::StatesTag{}, resourceGraph, resID); - - bool backBuffer = resTraits.residency == ResourceResidency::BACKBUFFER; - // when to dispatch a barrier on persistent: - // 1. resource been written in this frame; - // 2. first meet in this frame (no idea if any writes in next frame) - // 3. backbuffer present - bool needNextBarrier = (namesSet.find(resName) != namesSet.end()) || (rescStates.states == gfx::AccessFlagBit::NONE); - - // persistant resource states cached here - rescStates.states = transition.currStatus.accessFlag; - - if (!backBuffer && !needNextBarrier) { - continue; - } + return dependent; +} - auto passID = transition.currStatus.vertID; - if (batchedBarriers.find(passID) == batchedBarriers.end()) { - batchedBarriers.emplace(passID, BarrierNode{}); - } +bool checkResolveResource(const Graphs &graphs, + uint32_t ragVertID, + ResourceAccessNode &node, + const ccstd::pmr::vector &resolves, + AttachmentMap &colorMap) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + const auto passID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, ragVertID); + bool dependent = false; - Barrier nextFrameResBarrier{ - resID, - gfx::BarrierType::SPLIT_BEGIN, - nullptr, - externalResMap[externalPair.first].currStatus, - {}}; - - if (backBuffer) { - nextFrameResBarrier.endStatus = { - INVALID_ID, - gfx::ShaderStageFlagBit::NONE, - gfx::MemoryAccessBit::NONE, - gfx::PassType::PRESENT, - gfx::AccessFlagBit::PRESENT, - gfx::TextureUsageBit::NONE, - TextureRange{}, - }; - nextFrameResBarrier.type = gfx::BarrierType::FULL; - rescStates.states = gfx::AccessFlagBit::PRESENT; - } + for (const auto &pair : resolves) { + const auto &resolveTargetName = pair.target; - bool hasSubpass = !(batchedBarriers[passID].subpassBarriers.size() <= 1); - if (hasSubpass) { - // rpinfo instead - auto &fgRenderPassInfo = rag.rpInfos.at(passID); - auto iter = std::find(fgRenderPassInfo.orderedViews.begin(), fgRenderPassInfo.orderedViews.end(), resName.c_str()); - CC_ASSERT(iter != fgRenderPassInfo.orderedViews.end()); - auto index = std::distance(fgRenderPassInfo.orderedViews.begin(), iter); - index -= fgRenderPassInfo.rpInfo.depthStencilAttachment.format != gfx::Format::UNKNOWN; - fgRenderPassInfo.colorAccesses[index].nextAccess = nextFrameResBarrier.endStatus.accessFlag; - } else { - auto &rearBarriers = batchedBarriers[passID].blockBarrier.rearBarriers; - rearBarriers.emplace_back(nextFrameResBarrier); - } + const auto &resID = vertex(resolveTargetName, resourceGraph); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + + bool isDS = desc.format == gfx::Format::DEPTH_STENCIL; + auto accessFlag = isDS ? gfx::AccessFlagBit::DEPTH_STENCIL_ATTACHMENT_WRITE : gfx::AccessFlagBit::COLOR_ATTACHMENT_WRITE; + + gfx::ShaderStageFlagBit vis = gfx::ShaderStageFlagBit::FRAGMENT; + auto range = getResourceRange(resID, resourceGraph); + + ViewStatus viewStatus{resolveTargetName, AccessType::WRITE, vis, accessFlag, range}; + addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); + + const auto &[lastVertId, lastAccess] = dependencyCheck(resourceAccessGraph, ragVertID, resourceGraph, viewStatus); + tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); + tryAddEdge(lastVertId, ragVertID, relationGraph); + dependent = lastVertId != EXPECT_START_ID; + + AttachmentType attachmentType = isDS ? AttachmentType::DEPTH_STENCIL : AttachmentType::RENDER_TARGET; + colorMap.emplace(AttachmentSortKey{desc.sampleCount, + AccessType::WRITE, + ATTACHMENT_TYPE_WEIGHT[static_cast(attachmentType)], + resolveTargetName}, + ViewInfo{desc.format, + LayoutAccess{lastAccess, accessFlag}, + gfx::LoadOp::DISCARD, + gfx::StoreOp::STORE, + attachmentType}); } + return dependent; +} - { - const auto &resDescs = get(ResourceGraph::DescTag{}, resourceGraph); - auto genGFXBarrier = [&resDescs](std::vector &barriers) { - for (auto &passBarrier : barriers) { - const auto &desc = get(resDescs, passBarrier.resourceID); - if (desc.dimension == ResourceDimension::BUFFER) { - gfx::BufferBarrierInfo info; - info.prevAccesses = passBarrier.beginStatus.accessFlag; - info.nextAccesses = passBarrier.endStatus.accessFlag; - const auto &range = ccstd::get(passBarrier.endStatus.range); - info.offset = range.offset; - info.size = range.size; - info.type = passBarrier.type; - passBarrier.barrier = gfx::Device::getInstance()->getBufferBarrier(info); - } else { - gfx::TextureBarrierInfo info; - info.prevAccesses = passBarrier.beginStatus.accessFlag; - info.nextAccesses = passBarrier.endStatus.accessFlag; - const auto &range = ccstd::get(passBarrier.beginStatus.range); - info.baseMipLevel = range.mipLevel; - info.levelCount = range.levelCount; - info.baseSlice = range.firstSlice; - info.sliceCount = range.numSlices; - info.type = passBarrier.type; - passBarrier.barrier = gfx::Device::getInstance()->getTextureBarrier(info); - } - } - }; +uint32_t record(uint32_t index) { + uint32_t res = 1 << index; + return res; +} - constexpr static bool USING_RENDERPASS_DEP_INSTEAD_OF_BARRIER{true}; - if constexpr (USING_RENDERPASS_DEP_INSTEAD_OF_BARRIER) { - auto prune = [&rag, &renderGraph, &resourceGraph](std::vector &barriers) { - barriers.erase(std::remove_if(barriers.begin(), barriers.end(), [&rag, &renderGraph, &resourceGraph](Barrier &barrier) { - bool fromAttachment = isAttachmentAccess(barrier.beginStatus.accessFlag) || barrier.beginStatus.accessFlag == gfx::AccessFlagBit::NONE; - bool toAttachment = isAttachmentAccess(barrier.endStatus.accessFlag); - return toAttachment; - }), - barriers.end()); - }; - for (auto &passBarrierInfo : batchedBarriers) { - auto &passBarrierNode = passBarrierInfo.second; - prune(passBarrierNode.blockBarrier.frontBarriers); - prune(passBarrierNode.blockBarrier.rearBarriers); - } - } +uint32_t record(const ccstd::vector &indices) { + uint32_t res = 0; + for (auto attachmentIndex : indices) { + res |= 1 << attachmentIndex; + } + return res; +} - // generate gfx barrier - for (auto &passBarrierInfo : batchedBarriers) { - auto &passBarrierNode = passBarrierInfo.second; - genGFXBarrier(passBarrierNode.blockBarrier.frontBarriers); - genGFXBarrier(passBarrierNode.blockBarrier.rearBarriers); - for (auto &subpassBarrier : passBarrierNode.subpassBarriers) { - genGFXBarrier(subpassBarrier.frontBarriers); - genGFXBarrier(subpassBarrier.rearBarriers); - } +void extract(uint32_t val, ccstd::vector &preserves) { + uint32_t index = 0; + while (val) { + if (val & 0x1) { + preserves.emplace_back(index); } + val = val >> 1; + ++index; } +} - { - for (auto &[vert, fgRenderpassInfo] : rag.rpInfos) { - auto &colorAttachments = fgRenderpassInfo.rpInfo.colorAttachments; - for (uint32_t i = 0; i < colorAttachments.size(); ++i) { - const auto &colorAccess = fgRenderpassInfo.colorAccesses[i]; - colorAttachments[i].barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), colorAccess.prevAccess, colorAccess.nextAccess); - } - auto &dsAttachment = fgRenderpassInfo.rpInfo.depthStencilAttachment; - if (dsAttachment.format != gfx::Format::UNKNOWN) { - const auto &dsAccess = fgRenderpassInfo.dsAccess; - dsAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), dsAccess.prevAccess, dsAccess.nextAccess); - } - auto &dsResolveAttachment = fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; - if (dsResolveAttachment.format != gfx::Format::UNKNOWN) { - const auto &dsAccess = fgRenderpassInfo.dsResolveAccess; - dsResolveAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), dsAccess.prevAccess, dsAccess.nextAccess); - } +void getPreserves(gfx::RenderPassInfo &rpInfo) { + std::stack stack; + for (auto &info : rpInfo.subpasses) { + stack.push(&info); + } + + auto dsIndex = record(rpInfo.colorAttachments.size()); + auto dsMask = record(rpInfo.colorAttachments.size()) | record(rpInfo.colorAttachments.size() + 1); + + uint32_t laterRead{0}; + while (!stack.empty()) { + auto *tail = stack.top(); + stack.pop(); + + auto readRecord = record(tail->inputs); + auto writeRecord = record(tail->colors); + auto resolveRecord = record(tail->resolves); + + uint32_t dsRecord = 0; + if (tail->depthStencil != INVALID_ID) { + dsRecord |= record(tail->depthStencil); + } + if (tail->depthStencilResolve != INVALID_ID) { + dsRecord |= record(tail->depthStencilResolve); } + auto shown = readRecord | writeRecord | resolveRecord | dsRecord; + auto needPreserve = (shown | laterRead) ^ shown; + needPreserve = (needPreserve & dsMask) == dsMask ? (needPreserve & ~dsMask) | dsIndex : (needPreserve & ~dsMask); + extract(needPreserve, tail->preserves); + laterRead |= readRecord; } } -#pragma endregion BUILD_BARRIERS - -#pragma region PASS_REORDER -struct PassVisitor : boost::dfs_visitor<> { - using RLGVertex = RelationGraph::vertex_descriptor; - using RLGEdge = RelationGraph::edge_descriptor; - using InEdgeRange = std::pair; - using OutEdgeRange = std::pair; +uint32_t getDepthStencilSlot(uint32_t uniqueResourceCount, uint32_t resolveCount, bool hasDS) { + auto dsSlot = uniqueResourceCount - hasDS + resolveCount; + return dsSlot; +} - PassVisitor(RelationGraph &tcIn, CloseCircuits &circuitsIn) : _relationGraph(tcIn), _circuits(circuitsIn) {} +void startRenderPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - void start_vertex(RLGVertex u, const RelationGraph &g) {} + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - void discover_vertex(RLGVertex u, const RelationGraph &g) {} + auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, vertID); + if (pass.subpassGraph.subpasses.empty()) { + AttachmentMap colorMap(resourceAccessGraph.get_allocator()); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, vertID); + std::ignore = checkRasterViews(graphs, rlgVertID, accessNode, pass.rasterViews, colorMap); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); + fillRenderPassInfo(colorMap, fgRenderPassInfo, resourceGraph); + } else { + const auto &subpasses = pass.subpassGraph.subpasses; + uint32_t initVal{0}; + fgRenderPassInfo.resolveCount = std::accumulate(subpasses.begin(), subpasses.end(), initVal, [](uint32_t ct, const Subpass &subpass) { + return ct + subpass.resolvePairs.size(); + }); + } - void examine_edge(RLGEdge e, const RelationGraph &g) { + const auto &subpasses = pass.subpassGraph.subpasses; + uint32_t initVal{0}; + ccstd::pmr::set resSet{resourceAccessGraph.get_allocator()}; + for (const auto &subpass : subpasses) { + for (const auto &view : subpass.rasterViews) { + resSet.emplace(realID(view.first, resourceGraph)); + } + auto &dsResolveAttachment = fgRenderPassInfo.rpInfo.depthStencilResolveAttachment; + if (dsResolveAttachment.format != gfx::Format::UNKNOWN) { + const auto &dsAccess = fgRenderPassInfo.dsResolveAccess; + dsResolveAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), dsAccess.prevAccess, dsAccess.nextAccess); + } } + fgRenderPassInfo.uniqueRasterViewCount = resSet.size(); +} - void tree_edge(RLGEdge e, const RelationGraph &g) {} +void endRenderPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - void back_edge(RLGEdge e, const RelationGraph &g) {} + auto vertID = resourceAccessGraph.passIndex.at(passID); + auto rlgVertID = relationGraph.vertexMap.at(vertID); - void forward_or_cross_edge(RLGEdge e, const RelationGraph &g) { - // the vertex which: - // 1. is ancestor of targetID; - // 2. sourceID is reachable at this specific vert; - // is where the closed-path started. - // note that `reachable` may results to multiple paths, choose the shortest one. - auto sourceID = source(e, g); - auto targetID = target(e, g); + auto &node = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, vertID); + auto &fgRenderpassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, vertID); - using RhsRangePair = std::pair; + bool filledDS{fgRenderpassInfo.dsAccess.nextAccess != gfx::AccessFlags::NONE}; + bool filledDSResolve{fgRenderpassInfo.dsResolveAccess.nextAccess != gfx::AccessFlags::NONE}; + if (filledDSResolve && !filledDS) { + CC_ASSERT(fgRenderpassInfo.rpInfo.depthStencilAttachment.format == gfx::Format::UNKNOWN); + std::swap(fgRenderpassInfo.rpInfo.depthStencilAttachment, fgRenderpassInfo.rpInfo.depthStencilResolveAttachment); + std::swap(fgRenderpassInfo.dsAccess, fgRenderpassInfo.dsResolveAccess); + } - bool foundIntersect = false; - std::queue vertQ; - auto iterPair = in_edges(targetID, g); - vertQ.emplace(RhsRangePair{iterPair.first, iterPair}); + auto colorSize = fgRenderpassInfo.orderedViews.size(); + for (auto dsIter = fgRenderpassInfo.viewIndex.begin(); dsIter != fgRenderpassInfo.viewIndex.end(); ++dsIter) { + const auto &resName = dsIter->first; + const auto &parentName = dsIter->second.parentName; + if ((dsIter->second.attachmentIndex == gfx::INVALID_BINDING) && (resName == parentName)) { + fgRenderpassInfo.orderedViews.emplace_back(dsIter->first); + } + } - // from source vertex on this edge back to branch point - EdgeList rhsPath; - bool rootEdge = true; - while (!foundIntersect && !vertQ.empty()) { - auto rangePair = vertQ.front(); - vertQ.pop(); - auto range = rangePair.second; - for (auto iter = range.first; iter != range.second; ++iter) { - auto srcID = source((*iter), g); - if (sourceID == srcID) { - continue; - } - auto e = edge(srcID, sourceID, _relationGraph); - auto recordIter = rootEdge ? iter : rangePair.first; - if (!e.second) { - vertQ.emplace(RhsRangePair{recordIter, in_edges(srcID, g)}); - } else { - rhsPath = {(*iter), *recordIter}; - foundIntersect = true; - break; + if (!pass.subpassGraph.subpasses.empty()) { + // for (auto &subpassInfo : fgRenderpassInfo.rpInfo.subpasses) { + // if (subpassInfo.depthStencil != gfx::INVALID_BINDING) { + // if (subpassInfo.depthStencil != gfx::INVALID_BINDING) { + // subpassInfo.depthStencil = colorSize; + // } + // if (subpassInfo.depthStencilResolve != gfx::INVALID_BINDING) { + // subpassInfo.depthStencilResolve = colorSize + 1; + // } + // } + // } + getPreserves(fgRenderpassInfo.rpInfo); + } +} + +void startRenderSubpass(const Graphs &graphs, uint32_t passID, const RasterSubpass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + + auto parentID = parent(passID, renderGraph); + auto parentRagVertID = resourceAccessGraph.passIndex.at(parentID); + auto &fgRenderpassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, parentRagVertID); + AttachmentMap colorMap(resourceAccessGraph.get_allocator()); + + auto [hasDep, hasDS] = checkRasterViews(graphs, rlgVertID, accessNode, pass.rasterViews, colorMap); + hasDep |= checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); + hasDep |= checkResolveResource(graphs, rlgVertID, accessNode, pass.resolvePairs, colorMap); + fillRenderPassInfo(colorMap, fgRenderpassInfo, resourceGraph); + + auto &subpassInfo = fgRenderpassInfo.rpInfo.subpasses.emplace_back(); + auto &dependencies = fgRenderpassInfo.rpInfo.dependencies; + + // subpass info & subpass dependencies + for (const auto &pair : colorMap) { + const auto &sortKey = pair.first; + const std::string_view name = sortKey.name; + auto resID = vertex(sortKey.name, resourceGraph); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + const auto &[ignored, cIndex, isResolveView] = fgRenderpassInfo.viewIndex.at(name.data()); + if (isResolveView) { + auto resolveIter = std::find_if(pass.resolvePairs.begin(), pass.resolvePairs.end(), [&name](const ResolvePair &resolve) { + return strcmp(resolve.target.c_str(), name.data()) == 0; + }); + if (desc.format == gfx::Format::DEPTH_STENCIL) { + subpassInfo.depthStencilResolve = getDepthStencilSlot(fgRenderpassInfo.uniqueRasterViewCount, fgRenderpassInfo.resolveCount, hasDS) + 1; + if (resolveIter->mode != gfx::ResolveMode::NONE) { + subpassInfo.depthResolveMode = resolveIter->mode; } + if (resolveIter->mode1 != gfx::ResolveMode::NONE) { + subpassInfo.stencilResolveMode = resolveIter->mode1; + } + } else { + if (subpassInfo.resolves.empty()) { + subpassInfo.resolves.resize(pass.rasterViews.size() - hasDS, gfx::INVALID_BINDING); + } + const auto &resolveSrc = resolveIter->source; + const auto &resourceSrcInfo = fgRenderpassInfo.viewIndex.at(resolveSrc); + subpassInfo.resolves[resourceSrcInfo.attachmentIndex] = cIndex; } - rootEdge = false; - } - assert(foundIntersect); + } else { + if (desc.format == gfx::Format::DEPTH_STENCIL) { + auto dsSlot = getDepthStencilSlot(fgRenderpassInfo.uniqueRasterViewCount, fgRenderpassInfo.resolveCount, hasDS); + if (sortKey.accessType != AccessType::WRITE) { + subpassInfo.inputs.emplace_back(dsSlot); + } + if (sortKey.accessType != AccessType::READ) { + subpassInfo.depthStencil = dsSlot; + } + } else { + if (sortKey.accessType != AccessType::WRITE) { + subpassInfo.inputs.emplace_back(cIndex); + } + if (sortKey.accessType != AccessType::READ) { + subpassInfo.colors.emplace_back(cIndex); + } - using LhsRangePair = std::pair; - auto branchVert = source(rhsPath.first, g); - bool found = false; - std::queue forwardVertQ; - auto forwardIterPair = out_edges(branchVert, g); - forwardVertQ.emplace(LhsRangePair{forwardIterPair.first, forwardIterPair}); - EdgeList lhsPath; - rootEdge = true; - while (!found && !forwardVertQ.empty()) { - auto rangePair = forwardVertQ.front(); - forwardVertQ.pop(); - auto range = rangePair.second; - for (auto iter = range.first; iter != range.second; ++iter) { - if ((*iter) == rhsPath.first) { - continue; + if (sortKey.accessType == AccessType::READ_WRITE) { + auto &selfDependency = dependencies.emplace_back(); + selfDependency.srcSubpass = pass.subpassID; + selfDependency.dstSubpass = pass.subpassID; + selfDependency.prevAccesses = pair.second.access.nextAccess; + selfDependency.nextAccesses = pair.second.access.nextAccess; } - auto dstID = target((*iter), g); - auto e = edge(dstID, sourceID, _relationGraph); - auto recordIter = rootEdge ? iter : rangePair.first; - if (!e.second) { - forwardVertQ.emplace(LhsRangePair{recordIter, out_edges(dstID, g)}); - } else { - found = true; - lhsPath = {*recordIter, (*iter)}; - break; + } + } + + if (hasDep) { + auto &dependency = dependencies.emplace_back(); + auto lastIter = ++resourceAccessGraph.resourceAccess[name.data()].rbegin(); + bool isBuffer = desc.dimension == ResourceDimension::BUFFER; + if (accessDependent(lastIter->second.accessFlag, accessNode.resourceStatus.at(name.data()).accessFlag, isBuffer) && lastIter->second.accessFlag != gfx::AccessFlagBit::NONE) { + auto lastVert = lastIter->first; + auto lastPassID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, lastVert); + auto lastPassIndex = INVALID_ID; + if (holds(lastPassID, renderGraph) && (parent(lastPassID, renderGraph) == parentID)) { + const auto *lastPass = get_if(lastPassID, &renderGraph); + lastPassIndex = lastPass->subpassID; } + + auto &dependency = dependencies.emplace_back(); + dependency.srcSubpass = lastPassIndex; + dependency.dstSubpass = pass.subpassID; + dependency.prevAccesses = lastIter->second.accessFlag; + dependency.nextAccesses = pair.second.access.nextAccess; } - rootEdge = true; } - assert(found); - lhsPath.second = e; + } +} - _circuits.emplace_back(CloseCircuit{lhsPath, rhsPath}); - }; +void startComputeSubpass(const Graphs &graphs, uint32_t passID, const ComputeSubpass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; -private: - RelationGraph &_relationGraph; - CloseCircuits &_circuits; -}; + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); -// forward (vertex ascending): -// -- true: how much resource this pass writes to, which has an effect of later passes; -// -- false: how much resource this pass reads from, which is dependent from former passes. -auto evaluateHeaviness(const RAG &rag, const ResourceGraph &rescGraph, ResourceAccessGraph::vertex_descriptor vert, bool forward) { - const ResourceAccessNode &accessNode = get(RAG::AccessNodeTag{}, rag, vert); - int64_t score = 0; - bool forceAdjacent = false; - for (const auto &resc : accessNode.attachmentStatus) { - int64_t eval = 0; - auto rescID = resc.vertID; - const ResourceDesc &desc = get(ResourceGraph::DescTag{}, rescGraph, rescID); - const ResourceTraits &traits = get(ResourceGraph::TraitsTag{}, rescGraph, rescID); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + AttachmentMap colorMap(resourceAccessGraph.get_allocator()); - gfx::MemoryAccessBit substractFilter = forward ? gfx::MemoryAccessBit::READ_ONLY : gfx::MemoryAccessBit::WRITE_ONLY; - if (resc.access == substractFilter) { - // forward calculate write(s), backward calculate read(s). - continue; - } + auto parentID = parent(passID, renderGraph); + auto parentRagVertID = resourceAccessGraph.passIndex.at(parentID); + auto &fgRenderpassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, parentRagVertID); - switch (desc.dimension) { - case ResourceDimension::BUFFER: - eval = desc.width; - break; - case ResourceDimension::TEXTURE1D: - case ResourceDimension::TEXTURE2D: - case ResourceDimension::TEXTURE3D: - eval = gfx::formatSize(desc.format, desc.width, desc.height, desc.depthOrArraySize); - break; - } + std::ignore = checkRasterViews(graphs, rlgVertID, accessNode, pass.rasterViews, colorMap); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); - if (traits.residency == ResourceResidency::MEMORYLESS) { - forceAdjacent = true; - score = forward ? std::numeric_limits::lowest() : std::numeric_limits::max(); - break; - } - } - return std::make_tuple(forceAdjacent, score); -}; + fillRenderPassInfo(colorMap, fgRenderpassInfo, resourceGraph); +} -void evaluateAndTryMerge(const RAG &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, const RelationGraph &relationGraphTc, const RelationVerts &lhsVerts, const RelationVerts &rhsVerts) { - assert(lhsVerts.size() >= 2); - assert(rhsVerts.size() >= 2); +void startComputePass(const Graphs &graphs, uint32_t passID, const ComputePass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - auto evaluate = [&rag, &rescGraph, &relationGraph](RelationVert vert, bool forward) { - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); - return evaluateHeaviness(rag, rescGraph, ragVert, forward); + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); +} + +void startCopyPass(const Graphs &graphs, uint32_t passID, const CopyPass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + + auto &resg = resourceGraph; + auto &rag = resourceAccessGraph; + auto &rlg = relationGraph; + auto checkCopy = [&](const ccstd::pmr::string &resName, + uint32_t firstSlice, + uint32_t firstMip, + uint32_t firstPlane, + uint32_t sliceCount, + uint32_t mipCount, + bool read) { + auto srcID = vertex(resName, resg); + auto srcRange = getResourceRange(srcID, resg); + srcRange.firstSlice = firstSlice; + srcRange.mipLevel = firstMip; + srcRange.basePlane = firstPlane; + srcRange.numSlices = sliceCount; + srcRange.levelCount = mipCount; + + AccessType access = read ? AccessType::READ : AccessType::WRITE; + gfx::AccessFlags accessFlag = read ? gfx::AccessFlags::TRANSFER_READ : gfx::AccessFlags::TRANSFER_WRITE; + ViewStatus srcViewStatus{resName, access, gfx::ShaderStageFlagBit::NONE, accessFlag, srcRange}; + addAccessStatus(rag, resg, accessNode, srcViewStatus); + const auto &[lastVertSrc, ignore1] = dependencyCheck(rag, vertID, resg, srcViewStatus); + tryAddEdge(lastVertSrc, vertID, rag); + tryAddEdge(lastVertSrc, rlgVertID, rlg); }; - if (lhsVerts.size() == 2 || rhsVerts.size() == 2) { - /* - 1 ----------- 2 - \ __--/ - 3 --`` - no extra choice, only 1 - 3 - 2 - */ - const RelationVerts *shorterPath = lhsVerts.size() == 2 ? &lhsVerts : &rhsVerts; - remove_edge((*shorterPath)[0], (*shorterPath)[1], relationGraph); - } else { - // fist and last joint pass in this circuit don't get involved in reorder. - auto firstLhsNode = lhsVerts[1]; - auto lastLhsNode = lhsVerts[lhsVerts.size() - 2]; + for (const auto © : pass.copyPairs) { + checkCopy(copy.source, + copy.sourceFirstSlice, copy.sourceMostDetailedMip, copy.sourcePlaneSlice, + copy.numSlices, copy.mipLevels, true); - const auto &lhsBackwardStatus = evaluate(firstLhsNode, false); - bool lhsAdjacentToStart = std::get<0>(lhsBackwardStatus); - const auto &lhsForwardStatus = evaluate(lastLhsNode, true); - bool lhsAdjacentToEnd = std::get<0>(lhsForwardStatus); + checkCopy(copy.target, + copy.targetFirstSlice, copy.targetMostDetailedMip, copy.targetPlaneSlice, + copy.numSlices, copy.mipLevels, false); + } - auto firstRhsNode = rhsVerts[1]; - auto lastRhsNode = rhsVerts[rhsVerts.size() - 2]; + for (const auto &upload : pass.uploadPairs) { + checkCopy(upload.target, + upload.targetFirstSlice, upload.targetMostDetailedMip, upload.targetPlaneSlice, + upload.numSlices, upload.mipLevels, false); + } +} - const auto &rhsBackwardStatus = evaluate(firstRhsNode, true); - bool rhsAdjacentToStart = std::get<0>(rhsBackwardStatus); - const auto &rhsForwardStatus = evaluate(lastRhsNode, false); - bool rhsAdjacentToEnd = std::get<0>(rhsForwardStatus); +void startRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - if (lhsAdjacentToStart || rhsAdjacentToEnd || lhsAdjacentToEnd || rhsAdjacentToStart) { - const RelationVerts *formerPath = &lhsVerts; - const RelationVerts *latterPath = &rhsVerts; - if (rhsAdjacentToStart || lhsAdjacentToEnd) { - swap(formerPath, latterPath); - } + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - remove_edge((*latterPath)[0], (*latterPath)[1], relationGraph); - remove_edge((*formerPath)[formerPath->size() - 2], (*formerPath)[formerPath->size() - 1], relationGraph); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); +} - tryAddEdge((*formerPath)[formerPath->size() - 2], (*latterPath)[1], relationGraph); - } +namespace { +struct SliceNode { + bool full{false}; + ccstd::pmr::vector mips; +}; - assert(lhsVerts.size() >= 3 && rhsVerts.size() >= 3); - constexpr int64_t score = std::numeric_limits::lowest(); - ccstd::vector> candidateSections; - std::queue lhsSection; - for (size_t i = 1; i < lhsVerts.size(); ++i) { - auto tryE = edge(lhsVerts[i], lhsVerts[i - 1], relationGraphTc); - auto tryRE = edge(lhsVerts[i - 1], lhsVerts[i], relationGraphTc); - // check if original reachable - if (!tryE.second && !tryRE.second) { - remove_edge(lhsVerts[i - 1], lhsVerts[i], relationGraph); - candidateSections.emplace_back(lhsSection); - std::queue clearQ; - lhsSection.swap(clearQ); - } - auto e = edge(lhsVerts[i], lhsVerts[i - 1], relationGraph); - // verts comes in order, so either real edge exist or logic edge is added. - CC_ASSERT(e.second); +struct TextureNode { + bool full{false}; + ccstd::pmr::vector slices; +}; - lhsSection.emplace(e.first); +struct ResourceNode { + ccstd::pmr::vector planes; +}; +} // namespace + +bool rangeCheck(ccstd::pmr::map &status, + const ResourceDesc &desc, + const PmrString &targetName, + uint32_t firstSlice, uint32_t numSlices, + uint32_t firstMip, uint32_t mipLevels, + uint32_t planeIndex) { + if (status.find(targetName) == status.end()) { + status.emplace(targetName, ResourceNode{}); + } + + if (planeIndex >= status[targetName].planes.size()) { + status[targetName].planes.resize(planeIndex + 1); + status[targetName].planes[planeIndex].slices.resize(desc.depthOrArraySize); + for (auto &slice : status[targetName].planes[planeIndex].slices) { + slice.mips.resize(desc.mipLevels, std::numeric_limits::max()); + } + } + + // no spare space in target + bool check = !status[targetName].planes[planeIndex].full; + for (auto slice = firstSlice; slice < firstSlice + numSlices; ++slice) { + auto &slices = status[targetName].planes[planeIndex].slices; + // no spare space in this slice + check &= !slices[slice].full; + for (auto mip = firstMip; mip < firstMip + mipLevels; ++mip) { + auto &mips = slices[slice].mips; + // this mip has been taken + check &= mips[mip] == std::numeric_limits::max(); + mips[mip] = mip; + auto maxIter = std::max_element(mips.begin(), mips.end()); + if ((*maxIter) != std::numeric_limits::max()) { + // linear increasing + check &= (*maxIter) == mips.size() - 1; + slices[slice].full = true; + } } - if (candidateSections.empty()) { - // if this one is a tight edge(no logic edge, dependent from one to its next), - // keep this whole chain as a candidate. - remove_edge(lhsVerts[0], lhsVerts[1], relationGraph); - remove_edge(lhsVerts[lhsVerts.size() - 2], lhsVerts[lhsVerts.size() - 1], relationGraph); - candidateSections.emplace_back(std::move(lhsSection)); + if (std::all_of(slices.begin(), slices.end(), [](const SliceNode &sliceNode) { return sliceNode.full; })) { + status[targetName].planes[planeIndex].full = true; } + } + return check; +} - std::queue rhsSection; - for (size_t i = 1; i < rhsVerts.size(); ++i) { - auto tryE = edge(rhsVerts[i], rhsVerts[i - 1], relationGraphTc); - auto tryRE = edge(rhsVerts[i - 1], rhsVerts[i], relationGraphTc); - if (!tryE.second && !tryRE.second) { - remove_edge(rhsVerts[i - 1], rhsVerts[i], relationGraph); - candidateSections.emplace_back(rhsSection); - std::queue clearQ; - rhsSection.swap(clearQ); - } - auto e = edge(rhsVerts[i], rhsVerts[i - 1], relationGraph); - // verts comes in order, so either real edge exist or logic edge is added. - CC_ASSERT(e.second); - rhsSection.emplace(e.first); +bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const ResourceGraph& resourceGraph) { + bool check = true; + // ccstd::pmr::map sourceCheck; + ccstd::pmr::map targetCheck; + for (const auto &movePair : pass.movePairs) { + const auto &fromResName = movePair.source; + const auto fromResID = resourceGraph.valueIndex.at(fromResName); + const auto &fromResDesc = get(ResourceGraph::DescTag{}, resourceGraph, fromResID); + + const auto &toResName = movePair.target; + const auto toResID = resourceGraph.valueIndex.at(toResName); + const auto &toResDesc = get(ResourceGraph::DescTag{}, resourceGraph, toResID); + + const auto &fromResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, fromResID); + const auto &toResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, toResID); + auto commonUsage = fromResDesc.flags | toResDesc.flags; + + // bool sourceRangeValid = rangeCheck(targetCheck, toResDesc, fromResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); + bool targetRangeValid = rangeCheck(targetCheck, toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); + + uint32_t validConditions[] = { + !fromResTraits.hasSideEffects(), + rag.movedSourceStatus.find(toResName) == rag.movedSourceStatus.end(), + rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), + targetRangeValid, + fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, + fromResDesc.dimension == toResDesc.dimension, + fromResDesc.width == toResDesc.width, + fromResDesc.height == toResDesc.height, + fromResDesc.format == toResDesc.format, + fromResDesc.sampleCount == toResDesc.sampleCount, + (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer + }; + bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); + check &= val; + } + + // full destination + check &= std::all_of(targetCheck.begin(), targetCheck.end(), [](const auto &pair) { + const ResourceNode &resNode = pair.second; + return std::all_of(resNode.planes.begin(), resNode.planes.end(), [](const auto &textureNode) { + return textureNode.full; + }); + }); + + return check; + } + +void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + + if(moveValidation(pass, resourceAccessGraph, resourceGraph)) { + for(const auto& pair : pass.movePairs) { + auto srcResourceRange = getResourceRange(vertex(pair.source, resourceGraph), resourceGraph); + srcResourceRange.firstSlice = pair.targetFirstSlice; + srcResourceRange.mipLevel = pair.targetMostDetailedMip; + srcResourceRange.basePlane = pair.targetPlaneSlice; + + auto lastStatusIter = resourceAccessGraph.resourceAccess.at(pair.source).rbegin(); + resourceAccessGraph.movedSourceStatus.emplace(pair.source, AccessStatus{lastStatusIter->second.accessFlag, srcResourceRange}); + resourceAccessGraph.movedTarget[pair.target].emplace_back(pair.source); + resourceAccessGraph.resourceAccess[pair.target] = resourceAccessGraph.resourceAccess[pair.source]; + + auto targetResID = findVertex(pair.target, resourceGraph); + resourceAccessGraph.resourceIndex[pair.target] = targetResID; + + auto &rag = resourceAccessGraph; + std::function feedBack = [&](const ccstd::pmr::string &source, ResourceGraph::vertex_descriptor v) { + rag.resourceIndex[source] = v; + if (rag.movedTarget.find(source) != rag.movedTarget.end()) { + for (const auto &prt : rag.movedTarget[source]) { + feedBack(prt, v); + } + } + }; + feedBack(pair.source, targetResID); } - - // lhs verts already put in. - if (candidateSections.size() == 1) { - remove_edge(rhsVerts[0], rhsVerts[1], relationGraph); - remove_edge(rhsVerts[rhsVerts.size() - 2], rhsVerts[rhsVerts.size() - 1], relationGraph); - candidateSections.emplace_back(std::move(rhsSection)); + } else { + for(const auto& pair : pass.movePairs) { + CopyPass copyPass(resourceAccessGraph.get_allocator()); + copyPass.copyPairs.emplace_back(CopyPair( + pair.source, + pair.target, + pair.mipLevels, pair.numSlices, + 0, 0, 0, + pair.targetMostDetailedMip, pair.targetFirstSlice, pair.targetPlaneSlice)); + startCopyPass(graphs, passID, copyPass); } + } +} - assert(candidateSections.size() >= 2); +struct DependencyVisitor : boost::dfs_visitor<> { + void discover_vertex(RenderGraph::vertex_descriptor passID, + const AddressableView &gv) const { + visitObject( + passID, gv.mGraph, + [&](const RasterPass &pass) { + startRenderPass(graphs, passID, pass); + }, + [&](const RasterSubpass &pass) { + startRenderSubpass(graphs, passID, pass); + }, + [&](const ComputeSubpass &pass) { + startComputeSubpass(graphs, passID, pass); + }, + [&](const ComputePass &pass) { + startComputePass(graphs, passID, pass); + }, + [&](const CopyPass &pass) { + startCopyPass(graphs, passID, pass); + }, + [&](const MovePass &pass) { + startMovePass(graphs, passID, pass); + }, + [&](const RaytracePass &pass) { + startRaytracePass(graphs, passID, pass); + }, + [&](const auto & /*pass*/) { + // do nothing + }); + } - ScoreMap scMap; - auto tailVert = lhsVerts[0]; - while (!candidateSections.empty()) { - int64_t lightest = std::numeric_limits::max(); - uint32_t index = 0; - for (size_t i = 0; i < candidateSections.size(); ++i) { - auto e = candidateSections[i].front(); - auto srcVert = source(e, relationGraph); - auto dstVert = target(e, relationGraph); - int64_t srcBackwardScore = 0; - int64_t dstForwardScore = 0; - if (scMap.find(srcVert) == scMap.end()) { - auto res = evaluate(srcVert, false); - srcBackwardScore = std::get<1>(res); - res = evaluate(srcVert, true); - auto srcForwardScore = std::get<1>(res); - scMap.emplace(srcVert, std::pair(srcBackwardScore, srcForwardScore)); - } else { - srcBackwardScore = std::get<0>(scMap.at(srcVert)); - } - if (scMap.find(dstVert) == scMap.end()) { - auto res = evaluate(dstVert, false); - dstForwardScore = std::get<1>(res); - res = evaluate(dstVert, true); - auto dstBackwardScore = std::get<1>(res); - scMap.emplace(dstVert, std::pair(dstBackwardScore, dstForwardScore)); - } else { - dstForwardScore = std::get<1>(scMap.at(dstVert)); - } - - // we are in a simple path, so all the "input(this path)" resource of this path come from the first vertex, - // all the "output(this path)" come to the last vertex, other resources are "internally(this path)" produced and destroyed. - // so only input of first vertex and output of last vertex are taken into account. - // [simple path]: path without diverged edges. - auto score = dstForwardScore - srcBackwardScore; - if (lightest > score) { - lightest = score; - index = i; - } - } - auto e = candidateSections[index].front(); - candidateSections[index].pop(); - if (candidateSections[index].empty()) { - auto iter = candidateSections.begin(); - std::advance(iter, index); - candidateSections.erase(iter); - } - auto srcVert = source(e, relationGraph); - auto dstVert = target(e, relationGraph); - tryAddEdge(tailVert, srcVert, relationGraph); - tailVert = dstVert; - } - - tryAddEdge(tailVert, lhsVerts.back(), relationGraph); + void finish_vertex(RenderGraph::vertex_descriptor passID, + const AddressableView &gv) const { + visitObject( + passID, gv.mGraph, + [&](const RasterPass &pass) { + endRenderPass(graphs, passID, pass); + }, + [&](const auto & /*pass*/) { + // do nothing + }); } -} -// return : can be further reduced? -bool reduce(const RAG &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, RelationGraph &relationGraphTc, const CloseCircuit &circuit) { - auto checkPath = [&relationGraph](std::stack &vertices, RelationGraph::vertex_descriptor endVert, RelationVerts &stackTrace) { - bool simpleGraph = true; - while (!vertices.empty()) { - auto vert = vertices.top(); - vertices.pop(); - stackTrace.emplace_back(vert); + const Graphs &graphs; +}; - if (endVert == vert) { - break; - } +// status of resource access +void buildAccessGraph(const Graphs &graphs) { + // what we need: + // - pass dependency + // - pass attachment access + // AccessTable accessRecord; - if (out_degree(vert, relationGraph) > 1) { - simpleGraph = false; - break; - } - auto r = out_edges(vert, relationGraph); - for (auto rIter = r.first; rIter != r.second; ++rIter) { - auto dstID = target(*rIter, relationGraph); - vertices.push(dstID); - } - if (r.first == r.second) { - stackTrace.pop_back(); - } - } - return simpleGraph; - }; + const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + size_t numPasses = 0; + numPasses += renderGraph.rasterPasses.size(); + numPasses += renderGraph.computePasses.size(); + numPasses += renderGraph.copyPasses.size(); + numPasses += renderGraph.movePasses.size(); + numPasses += renderGraph.raytracePasses.size(); - // check if there is a sub branch on lhs - auto lhsEdges = circuit.first; - auto startVert = target(lhsEdges.first, relationGraph); - auto endVert = source(lhsEdges.second, relationGraph); + resourceAccessGraph.reserve(static_cast(numPasses)); + resourceAccessGraph.resourceNames.reserve(128); + resourceAccessGraph.resourceIndex.reserve(128); - std::stack vertices; - vertices.emplace(startVert); + resourceAccessGraph.topologicalOrder.reserve(numPasses); + resourceAccessGraph.topologicalOrder.clear(); + resourceAccessGraph.resourceLifeRecord.reserve(resourceGraph.names.size()); - RelationVerts lhsVisited; - auto branchStartVert = source(lhsEdges.first, relationGraph); - auto branchEndVert = target(lhsEdges.second, relationGraph); - lhsVisited.push_back(branchStartVert); - // check if there is a branch on lhs path - if (!checkPath(vertices, endVert, lhsVisited)) { - return false; + if (!resourceAccessGraph.resourceLifeRecord.empty()) { + resourceAccessGraph.resourceLifeRecord.clear(); } - lhsVisited.push_back(branchEndVert); - // if it's a simple graph, lhs path must can be dfs to the end at the first time. - assert(vertices.empty()); - auto rhsEdges = circuit.second; - startVert = target(rhsEdges.first, relationGraph); - endVert = source(rhsEdges.second, relationGraph); - vertices.emplace(startVert); + if (!resourceAccessGraph.leafPasses.empty()) { + resourceAccessGraph.leafPasses.clear(); + } + if (!resourceAccessGraph.culledPasses.empty()) { + resourceAccessGraph.culledPasses.clear(); + } - RelationVerts rhsVisited; - rhsVisited.push_back(branchStartVert); - if (!checkPath(vertices, endVert, rhsVisited)) { - return false; + // const auto &names = get(RenderGraph::Name, renderGraph); + for (size_t i = 1; i <= numPasses; ++i) { + resourceAccessGraph.leafPasses.emplace(i, LeafStatus{false, true}); } - rhsVisited.push_back(branchEndVert); - // merge this circuit - // from - /* 2 - 3 - 4 - / \ - 1 8 - \ / - 5 - 6 - 7 + auto startID = add_vertex(resourceAccessGraph, INVALID_ID - 1); + CC_EXPECTS(startID == EXPECT_START_ID); - to - 1 - A - B - 8 or 1 - B - A -8 depends on algorithm + add_vertex(relationGraph, startID); - ${A} : 2 - 3 - 4 - ${B} : 5 - 6 - 7 - */ + DependencyVisitor visitor{{}, graphs}; + auto colors = renderGraph.colors(renderGraph.resource()); + AddressableView gv{renderGraph}; + for (const auto passID : renderGraph.sortedVertices) { + if (!holds(passID, renderGraph) && !holds(passID, renderGraph)) { + boost::depth_first_visit(gv, passID, visitor, get(colors, renderGraph)); + } + } - evaluateAndTryMerge(rag, rescGraph, relationGraph, relationGraphTc, lhsVisited, rhsVisited); + auto &rag = resourceAccessGraph; + auto branchCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) -> void { + CC_EXPECTS(out_degree(vertex, rag) == 0); + using FuncType = void (*)(ResourceAccessGraph::vertex_descriptor, ResourceAccessGraph &); + static FuncType leafCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) { + rag.culledPasses.emplace(vertex); + auto &attachments = get(ResourceAccessGraph::PassNodeTag{}, rag, vertex); + attachments.resourceStatus.clear(); + auto inEdges = in_edges(vertex, rag); + for (auto iter = inEdges.first; iter < inEdges.second;) { + auto inEdge = *iter; + auto srcVert = source(inEdge, rag); + remove_edge(inEdge, rag); + if (out_degree(srcVert, rag) == 0) { + leafCulling(srcVert, rag); + } + inEdges = in_edges(vertex, rag); + iter = inEdges.first; + } + }; + leafCulling(vertex, rag); + }; - return true; -} + // no present pass found, add a fake node to gather leaf node(s). + if (resourceAccessGraph.presentPassID == 0xFFFFFFFF) { + auto ragEndNode = add_vertex(rag, RenderGraph::null_vertex()); + auto rlgEndNode = add_vertex(relationGraph, ragEndNode); + // keep sync before pass reorder done. + CC_EXPECTS(ragEndNode == rlgEndNode); + resourceAccessGraph.presentPassID = ragEndNode; + auto iter = resourceAccessGraph.leafPasses.find(ragEndNode); + constexpr bool isExternal = true; + constexpr bool needCulling = false; + if (iter == resourceAccessGraph.leafPasses.end()) { + resourceAccessGraph.leafPasses.emplace(ragEndNode, LeafStatus{isExternal, needCulling}); + } else { + resourceAccessGraph.leafPasses.at(ragEndNode) = LeafStatus{isExternal, needCulling}; + } + } -template -void applyRelation(RelationGraph &relationGraph, const TargetGraph &targetGraph) { - CC_EXPECTS(relationGraph.vertices.size() == targetGraph.vertices.size()); + // make leaf node closed walk for pass reorder + for (auto pass : resourceAccessGraph.leafPasses) { + bool isExternal = pass.second.isExternal; + bool needCulling = pass.second.needCulling; - // remove all edges - for (auto vert : targetGraph.vertices) { - clear_in_edges(vert, targetGraph); - clear_out_edges(vert, targetGraph); + if (pass.first != resourceAccessGraph.presentPassID) { + if (isExternal && !needCulling) { + add_edge(pass.first, resourceAccessGraph.presentPassID, resourceAccessGraph); + } else { + // write into transient resources, culled + if constexpr (ENABLE_BRANCH_CULLING) { + branchCulling(pass.first, resourceAccessGraph); + } + } + } + } + for (auto rit = resourceAccessGraph.culledPasses.rbegin(); rit != resourceAccessGraph.culledPasses.rend(); ++rit) { + // remove culled vertices, std::less make this set ascending order, so reverse iterate + remove_vertex(*rit, relationGraph); } - for (auto vert : relationGraph.vertices) { - auto inEdges = in_edges(vert, relationGraph); - for (auto e : makeRange(inEdges)) { - auto srcVert = source(e, relationGraph); - // auto checkEdge = edge(srcVert, vert, targetGraph); - add_edge(srcVert, vert, targetGraph); - } + for (auto rlgVert : makeRange(vertices(relationGraph))) { + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); + rag.topologicalOrder.emplace_back(ragVert); } } -void passReorder(FrameGraphDispatcher &fgDispatcher) { +#pragma region BUILD_BARRIERS +void buildBarriers(FrameGraphDispatcher &fgDispatcher) { auto *scratch = fgDispatcher.scratch; - const auto &renderGraph = fgDispatcher.graph; + const auto &renderGraph = fgDispatcher.renderGraph; const auto &layoutGraph = fgDispatcher.layoutGraph; auto &resourceGraph = fgDispatcher.resourceGraph; auto &relationGraph = fgDispatcher.relationGraph; auto &rag = fgDispatcher.resourceAccessGraph; + // record resource current in-access and out-access for every single node if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, resourceGraph, layoutGraph, rag, relationGraph}; + const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; buildAccessGraph(graphs); fgDispatcher._accessGraphBuilt = true; } - { - // determine do mem saving how many times - RelationGraph relationGraphTc(fgDispatcher.get_allocator()); - boost::transitive_closure(relationGraph, relationGraphTc); + auto getGFXBarrier = [&resourceGraph](const Barrier &barrier) { + gfx::GFXObject *gfxBarrier{nullptr}; + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, barrier.resourceID); + if (desc.dimension == ResourceDimension::BUFFER) { + gfx::BufferBarrierInfo info; + info.prevAccesses = barrier.beginStatus.accessFlag; + info.nextAccesses = barrier.endStatus.accessFlag; + const auto &range = barrier.endStatus.range; + info.offset = 0; + info.size = range.depthOrArraySize; + info.type = barrier.type; + gfxBarrier = gfx::Device::getInstance()->getBufferBarrier(info); + } else { + gfx::TextureBarrierInfo info; + info.prevAccesses = barrier.beginStatus.accessFlag; + info.nextAccesses = barrier.endStatus.accessFlag; + const auto &range = barrier.beginStatus.range; + info.baseMipLevel = range.mipLevel; + info.levelCount = range.levelCount; + info.baseSlice = range.firstSlice; + info.sliceCount = range.numSlices; + info.type = barrier.type; + gfxBarrier = gfx::Device::getInstance()->getTextureBarrier(info); + } + return gfxBarrier; + }; - CloseCircuits circuits; - std::vector crossEdges; - PassVisitor visitor(relationGraphTc, circuits); - auto colors = relationGraph.colors(scratch); - boost::depth_first_search(relationGraph, visitor, get(colors, relationGraph)); + // found pass id in this map ? barriers you should commit when run into this pass + // : or no extra barrier needed. + for (auto &accessPair : rag.resourceAccess) { + const auto &resName = accessPair.first; + if (rag.movedSourceStatus.find(resName) != rag.movedSourceStatus.end()) { + // moved, history of this resource access will be copied to moved target. + continue; + } - float percent = 0.0F; - uint32_t count = 0; - auto total = circuits.size(); + const auto &resID = findVertex(resName, resourceGraph); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + bool isBuffer = desc.dimension == ResourceDimension::BUFFER; + + const auto &accessRecord = accessPair.second; + auto iter = accessRecord.begin(); + auto nextIter = iter; + std::advance(nextIter, 1); + for (; nextIter != accessRecord.end(); ++iter, ++nextIter) { + auto srcRagVertID = iter->first; + auto dstRagVertID = nextIter->first; + auto srcPassID = get(ResourceAccessGraph::PassIDTag{}, rag, srcRagVertID); + auto dstPassID = get(ResourceAccessGraph::PassIDTag{}, rag, dstRagVertID); + + if (holds(dstPassID, renderGraph) || holds(dstPassID, renderGraph)) { + const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, dstRagVertID); + if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end()) { + // renderpass info instead + continue; + } + } - float memsavePercent = 1.0F - fgDispatcher._paralellExecWeight; - for (auto iter = circuits.begin(); (iter != circuits.end()) && (percent < memsavePercent);) { - bool reduced = reduce(rag, resourceGraph, relationGraph, relationGraphTc, (*iter)); - if (reduced) { - ++count; - iter = circuits.erase(iter); - percent = count / static_cast(total); - } else { - ++iter; + // subpass layout transition + if ((srcRagVertID != 0) && (holds(srcPassID, renderGraph) || holds(srcPassID, renderGraph))) { + auto ragVertID = srcRagVertID; + if (holds(srcPassID, renderGraph)) { + auto parentID = parent(srcPassID, renderGraph); + ragVertID = rag.passIndex.at(parentID); + } + // RenderPass Info + auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, ragVertID); + std::string_view resName = get(ResourceGraph::NameTag{}, resourceGraph, resID); + auto colorIter = std::find(fgRenderPassInfo.orderedViews.begin(), fgRenderPassInfo.orderedViews.end(), resName); + auto colorIndex = std::distance(fgRenderPassInfo.orderedViews.begin(), colorIter); + if (colorIndex < fgRenderPassInfo.colorAccesses.size()) { + fgRenderPassInfo.colorAccesses[colorIndex].nextAccess = nextIter->second.accessFlag; + } else if (colorIndex == fgRenderPassInfo.colorAccesses.size()) { + fgRenderPassInfo.dsAccess.nextAccess = nextIter->second.accessFlag; + } else if (colorIndex == fgRenderPassInfo.colorAccesses.size() + 1) { + fgRenderPassInfo.dsResolveAccess.nextAccess = nextIter->second.accessFlag; + } + + if (holds(srcPassID, renderGraph) && + accessDependent(iter->second.accessFlag, nextIter->second.accessFlag, isBuffer)) { + const auto *subpass = get_if(srcPassID, &renderGraph); + CC_ASSERT(subpass); + auto subpassID = subpass->subpassID; + auto &dependency = fgRenderPassInfo.rpInfo.dependencies.emplace_back(); + dependency.srcSubpass = subpass->subpassID; + dependency.dstSubpass = INVALID_ID; + dependency.prevAccesses = iter->second.accessFlag; + dependency.nextAccesses = nextIter->second.accessFlag; + } + continue; + } + + // undefined access + if (iter == accessRecord.begin()) { + auto &dstBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, dstRagVertID); + auto &firstMeetBarrier = dstBarrierNode.frontBarriers.emplace_back(); + firstMeetBarrier.resourceID = resID; + firstMeetBarrier.type = gfx::BarrierType::FULL; + firstMeetBarrier.beginVert = dstPassID; + firstMeetBarrier.endVert = dstPassID; + firstMeetBarrier.beginStatus = iter->second; + firstMeetBarrier.endStatus = nextIter->second; + firstMeetBarrier.barrier = getGFXBarrier(firstMeetBarrier); + } else if (accessDependent(iter->second.accessFlag, nextIter->second.accessFlag, isBuffer)) { + auto &srcBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, srcRagVertID); + auto &beginBarrier = srcBarrierNode.rearBarriers.emplace_back(); + beginBarrier.resourceID = resID; + beginBarrier.beginVert = srcPassID; + beginBarrier.endVert = dstPassID; + beginBarrier.beginStatus = iter->second; + beginBarrier.endStatus = nextIter->second; + if (isPassExecAdjecent(iter->first, nextIter->first)) { + beginBarrier.type = gfx::BarrierType::FULL; + } else { + beginBarrier.type = gfx::BarrierType::SPLIT_BEGIN; + + auto &dstBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, dstRagVertID); + auto &endBarrier = dstBarrierNode.frontBarriers.emplace_back(); + endBarrier.resourceID = resID; + endBarrier.type = gfx::BarrierType::SPLIT_END; + endBarrier.beginVert = srcPassID; + endBarrier.endVert = dstPassID; + endBarrier.beginStatus = iter->second; + endBarrier.endStatus = nextIter->second; + endBarrier.barrier = getGFXBarrier(endBarrier); + } + beginBarrier.barrier = getGFXBarrier(beginBarrier); + } + } + const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, resID); + auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resID); + if (traits.hasSideEffects()) { + states.states = iter->second.accessFlag; + if (traits.residency == ResourceResidency::BACKBUFFER) { + auto lastAccessPassID = get(ResourceAccessGraph::PassIDTag{}, rag, iter->first); + auto &barrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, iter->first); + auto &presentBarrier = barrierNode.rearBarriers.emplace_back(); + presentBarrier.resourceID = resID; + presentBarrier.type = gfx::BarrierType::FULL; + presentBarrier.beginVert = lastAccessPassID; + presentBarrier.endVert = lastAccessPassID; + presentBarrier.beginStatus = iter->second; + presentBarrier.endStatus = {gfx::AccessFlagBit::PRESENT, iter->second.range}; + presentBarrier.barrier = getGFXBarrier(presentBarrier); + + states.states = gfx::AccessFlagBit::NONE; } } + } - // topological sort - rag.topologicalOrder.clear(); - bool empty = relationGraph._vertices.empty(); - ScoreMap scoreMap; - RelationVerts candidates; - candidates.push_back(EXPECT_START_ID); - - std::vector candidateBuffer; - uint32_t coloredVerts = 0; - while (coloredVerts < relationGraph._vertices.size()) { - // decreasing order, pop back from vector, push into queue, then it's ascending order. - std::sort(candidates.begin(), candidates.end(), [&](RelationVert lhsVert, RelationVert rhsVert) { - int64_t lhsForwardScore{0}; - int64_t rhsForwardScore{0}; - int64_t lhsBackwardScore{0}; - int64_t rhsBackwardScore{0}; - if (scoreMap.find(lhsVert) == scoreMap.end()) { - auto lhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, lhsVert); - const auto &lhsForwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, true); - lhsForwardScore = get<1>(lhsForwardStatus); - const auto &lhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, false); - lhsBackwardScore = get<1>(lhsBackwardStatus); - scoreMap.emplace(lhsVert, std::pair{lhsBackwardScore, lhsForwardScore}); - } else { - lhsBackwardScore = scoreMap[lhsVert].first; - lhsForwardScore = scoreMap[lhsVert].second; - } - - if (scoreMap.find(rhsVert) == scoreMap.end()) { - auto rhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, rhsVert); - const auto &rhsForwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, true); - rhsForwardScore = get<1>(rhsForwardStatus); - const auto &rhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, false); - rhsBackwardScore = get<1>(rhsBackwardStatus); - scoreMap.emplace(rhsVert, std::pair{rhsBackwardScore, rhsForwardScore}); - } else { - rhsBackwardScore = scoreMap[rhsVert].first; - rhsForwardScore = scoreMap[rhsVert].second; - } - return lhsBackwardScore - lhsForwardScore > rhsBackwardScore - rhsForwardScore; - }); - - const auto vert = candidates.back(); - candidates.pop_back(); - - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); - rag.topologicalOrder.emplace_back(ragVert); - if (!candidateBuffer.empty()) { - candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); - candidateBuffer.clear(); - } - - for (const auto nextGeneration : makeRange(out_edges(vert, relationGraph))) { - auto targetID = target(nextGeneration, relationGraph); - if (in_degree(targetID, relationGraph) == 1) { - candidateBuffer.emplace_back(targetID); - } - } - - auto deprecatedEdges = out_edges(vert, relationGraph); - for (auto iter = deprecatedEdges.first; iter < deprecatedEdges.second;) { - remove_edge(*iter, relationGraph); - deprecatedEdges = out_edges(vert, relationGraph); - iter = deprecatedEdges.first; + { + for (auto &fgRenderpassInfo : rag.rpInfo) { + auto &colorAttachments = fgRenderpassInfo.rpInfo.colorAttachments; + uint32_t count{0}; + for (auto &color : colorAttachments) { + const auto &colorAccess = fgRenderpassInfo.colorAccesses[count]; + color.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), + colorAccess.prevAccess, + colorAccess.nextAccess); + ++count; } - - if (candidates.empty()) { - candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); - candidateBuffer.clear(); + auto &dsAttachment = fgRenderpassInfo.rpInfo.depthStencilAttachment; + if (dsAttachment.format != gfx::Format::UNKNOWN) { + const auto &dsAccess = fgRenderpassInfo.dsAccess; + dsAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), + dsAccess.prevAccess, + dsAccess.nextAccess); } - - coloredVerts++; - } - - // remove all edges - for (auto vert : makeRange(vertices(rag))) { - clear_in_edges(vert, rag); - clear_out_edges(vert, rag); - } - - // apply relation - for (auto rlgVert : makeRange(vertices(relationGraph))) { - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); - auto inEdges = in_edges(rlgVert, relationGraph); - for (auto e : makeRange(inEdges)) { - auto srcRlgVert = source(e, relationGraph); - auto srcRagVert = get(RelationGraph::DescIDTag{}, relationGraph, srcRlgVert); - add_edge(srcRagVert, ragVert, rag); + auto &dsResolveAttachment = fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; + if (dsResolveAttachment.format != gfx::Format::UNKNOWN) { + const auto &dsResolveAccess = fgRenderpassInfo.dsResolveAccess; + dsResolveAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), + dsResolveAccess.prevAccess, + dsResolveAccess.nextAccess); } } } } +#pragma endregion BUILD_BARRIERS -#pragma endregion PASS_REORDER +#pragma region PASS_REORDER -void memoryAliasing(FrameGraphDispatcher &fgDispatcher) { -} +struct PassVisitor : boost::dfs_visitor<> { + using RLGVertex = RelationGraph::vertex_descriptor; + using RLGEdge = RelationGraph::edge_descriptor; + using InEdgeRange = std::pair; + using OutEdgeRange = std::pair; -#pragma region assisstantFuncDefinition -template -bool tryAddEdge(uint32_t srcVertex, uint32_t dstVertex, Graph &graph) { - auto e = edge(srcVertex, dstVertex, graph); - if (!e.second) { - auto res = add_edge(srcVertex, dstVertex, graph); - CC_ENSURES(res.second); - return true; - } - return false; -} + PassVisitor(RelationGraph &tcIn, CloseCircuits &circuitsIn) : _relationGraph(tcIn), _circuits(circuitsIn) {} -bool isTransitionStatusDependent(const AccessStatus &lhs, const AccessStatus &rhs) { - return !(isReadOnlyAccess(lhs.accessFlag) && isReadOnlyAccess(rhs.accessFlag)); -} + void start_vertex(RLGVertex u, const RelationGraph &g) {} -auto mapTextureFlags(ResourceFlags flags) { - gfx::TextureUsage usage = gfx::TextureUsage::NONE; - if ((flags & ResourceFlags::SAMPLED) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::SAMPLED; - } - if ((flags & ResourceFlags::STORAGE) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::STORAGE; - } - if ((flags & ResourceFlags::SHADING_RATE) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::SHADING_RATE; - } - if ((flags & ResourceFlags::COLOR_ATTACHMENT) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::COLOR_ATTACHMENT; - } - if ((flags & ResourceFlags::DEPTH_STENCIL_ATTACHMENT) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT; - } - if ((flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::INPUT_ATTACHMENT; + void discover_vertex(RLGVertex u, const RelationGraph &g) {} + + void examine_edge(RLGEdge e, const RelationGraph &g) { } - return usage; -} -auto getResourceStatus(PassType passType, const PmrString &name, gfx::MemoryAccess memAccess, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph, bool rasterized) { - ResourceUsage usage; - gfx::ShaderStageFlags vis{gfx::ShaderStageFlags::NONE}; - vis |= visibility; - gfx::AccessFlags accesFlag; - auto vertex = resourceGraph.valueIndex.at(name); - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex); - if (desc.dimension == ResourceDimension::BUFFER) { - gfx::BufferUsage bufferUsage{gfx::BufferUsage::NONE}; - // copy is not included in this logic because copy can be set TRANSFER_xxx directly. - if (gfx::hasFlag(memAccess, gfx::MemoryAccessBit::WRITE_ONLY)) { - bufferUsage = gfx::BufferUsage::STORAGE; - } + void tree_edge(RLGEdge e, const RelationGraph &g) {} - if (gfx::hasFlag(memAccess, gfx::MemoryAccessBit::READ_ONLY)) { - bool uniformFlag = (desc.flags & ResourceFlags::UNIFORM) != ResourceFlags::NONE; - bool storageFlag = (desc.flags & ResourceFlags::STORAGE) != ResourceFlags::NONE; + void back_edge(RLGEdge e, const RelationGraph &g) {} - // CC_EXPECTS(uniformFlag ^ storageFlag); - // uniform or read-only storage buffer - bufferUsage = uniformFlag ? gfx::BufferUsage::UNIFORM : gfx::BufferUsage::STORAGE; - } + void forward_or_cross_edge(RLGEdge e, const RelationGraph &g) { + // the vertex which: + // 1. is ancestor of targetID; + // 2. sourceID is reachable at this specific vert; + // is where the closed-path started. + // note that `reachable` may results to multiple paths, choose the shortest one. + auto sourceID = source(e, g); + auto targetID = target(e, g); - if (passType == PassType::COMPUTE) { - vis |= gfx::ShaderStageFlagBit::COMPUTE; - } + using RhsRangePair = std::pair; - // those buffers not found in descriptorlayout but appear here, - // can and only can be VERTEX/INDEX/INDIRECT BUFFER, - // only copy pass is allowed. - if (vis == gfx::ShaderStageFlags::NONE) { - CC_EXPECTS(passType == PassType::COPY); - } - usage = bufferUsage; - accesFlag = gfx::getAccessFlags(bufferUsage, gfx::MemoryUsage::DEVICE, memAccess, vis); - } else { - // can't find this resource in layoutdata, not in descriptor so either input or output attachment. - gfx::TextureUsage texUsage = gfx::TextureUsage::NONE; + bool foundIntersect = false; + std::queue vertQ; + auto iterPair = in_edges(targetID, g); + vertQ.emplace(RhsRangePair{iterPair.first, iterPair}); - // TODO(Zeqiang): visbility of slot name "_" not found - if (hasFlag(memAccess, gfx::MemoryAccess::READ_ONLY)) { - if ((desc.flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE && rasterized) { - texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::INPUT_ATTACHMENT)); - } else { - texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::SAMPLED | gfx::TextureUsage::STORAGE | gfx::TextureUsage::SHADING_RATE | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT)); + // from source vertex on this edge back to branch point + EdgeList rhsPath; + bool rootEdge = true; + while (!foundIntersect && !vertQ.empty()) { + auto rangePair = vertQ.front(); + vertQ.pop(); + auto range = rangePair.second; + for (auto iter = range.first; iter != range.second; ++iter) { + auto srcID = source((*iter), g); + if (sourceID == srcID) { + continue; + } + auto e = edge(srcID, sourceID, _relationGraph); + auto recordIter = rootEdge ? iter : rangePair.first; + if (!e.second) { + vertQ.emplace(RhsRangePair{recordIter, in_edges(srcID, g)}); + } else { + rhsPath = {(*iter), *recordIter}; + foundIntersect = true; + break; + } } + rootEdge = false; } + assert(foundIntersect); - if (hasFlag(memAccess, gfx::MemoryAccess::WRITE_ONLY)) { - texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::STORAGE)); + using LhsRangePair = std::pair; + auto branchVert = source(rhsPath.first, g); + bool found = false; + std::queue forwardVertQ; + auto forwardIterPair = out_edges(branchVert, g); + forwardVertQ.emplace(LhsRangePair{forwardIterPair.first, forwardIterPair}); + EdgeList lhsPath; + rootEdge = true; + while (!found && !forwardVertQ.empty()) { + auto rangePair = forwardVertQ.front(); + forwardVertQ.pop(); + auto range = rangePair.second; + for (auto iter = range.first; iter != range.second; ++iter) { + if ((*iter) == rhsPath.first) { + continue; + } + auto dstID = target((*iter), g); + auto e = edge(dstID, sourceID, _relationGraph); + auto recordIter = rootEdge ? iter : rangePair.first; + if (!e.second) { + forwardVertQ.emplace(LhsRangePair{recordIter, out_edges(dstID, g)}); + } else { + found = true; + lhsPath = {*recordIter, (*iter)}; + break; + } + } + rootEdge = true; } + assert(found); + lhsPath.second = e; - if (vis == gfx::ShaderStageFlags::NONE) { - vis = passType == gfx::PassType::RASTER ? gfx::ShaderStageFlags::FRAGMENT : gfx::ShaderStageFlags::COMPUTE; - } + _circuits.emplace_back(CloseCircuit{lhsPath, rhsPath}); + }; - usage = texUsage; - accesFlag = gfx::getAccessFlags(texUsage, memAccess, vis); - } +private: + RelationGraph &_relationGraph; + CloseCircuits &_circuits; +}; - return std::make_tuple(vis, usage, accesFlag); -} +// forward (vertex ascending): +// -- true: how much resource this pass writes to, which has an effect of later passes; +// -- false: how much resource this pass reads from, which is dependent from former passes. +auto evaluateHeaviness(const ResourceAccessGraph &rag, const ResourceGraph &rescGraph, ResourceAccessGraph::vertex_descriptor vert, bool forward) { + const ResourceAccessNode &accessNode = get(ResourceAccessGraph::PassNodeTag{}, rag, vert); + int64_t score = 0; + bool forceAdjacent = false; + for (const auto &pair : accessNode.resourceStatus) { + int64_t eval = 0; + auto rescID = rag.resourceIndex.at(pair.first); + const ResourceDesc &desc = get(ResourceGraph::DescTag{}, rescGraph, rescID); + const ResourceTraits &traits = get(ResourceGraph::TraitsTag{}, rescGraph, rescID); -void addCopyAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status, const Range &range) { - const auto &[name, passType, visibility, access, accessFlag, usage] = status; - CC_EXPECTS(hasAnyFlags(accessFlag, gfx::AccessFlags::TRANSFER_READ | gfx::AccessFlags::TRANSFER_WRITE)); + const auto &resc = pair.second; + if (!(isReadOnlyAccess(resc.accessFlag) ^ forward)) { + // forward calculate write(s), backward calculate read(s). + continue; + } - uint32_t rescID = rg.valueIndex.at(name); + switch (desc.dimension) { + case ResourceDimension::BUFFER: + eval = desc.width; + break; + case ResourceDimension::TEXTURE1D: + case ResourceDimension::TEXTURE2D: + case ResourceDimension::TEXTURE3D: + eval = gfx::formatSize(desc.format, desc.width, desc.height, desc.depthOrArraySize); + break; + } - CC_EXPECTS(rg.valueIndex.find(name) != rg.valueIndex.end()); - if (std::find(rag.resourceNames.begin(), rag.resourceNames.end(), name) == rag.resourceNames.end()) { - rag.resourceIndex.emplace(name, rescID); - rag.resourceNames.emplace_back(name); + if (traits.residency == ResourceResidency::MEMORYLESS) { + forceAdjacent = true; + score = forward ? std::numeric_limits::lowest() : std::numeric_limits::max(); + break; + } } + return std::make_tuple(forceAdjacent, score); +}; - node.attachmentStatus.emplace_back(AccessStatus{ - rescID, - visibility, - access, - passType, - accessFlag, - usage, - range, - }); -} +void evaluateAndTryMerge(const ResourceAccessGraph &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, const RelationGraph &relationGraphTc, const RelationVerts &lhsVerts, const RelationVerts &rhsVerts) { + assert(lhsVerts.size() >= 2); + assert(rhsVerts.size() >= 2); -PmrString addAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status) { - const auto &[name, passType, visibility, access, accessFlag, usage] = status; - uint32_t rescID = rg.valueIndex.at(name); - const auto &resourceDesc = get(ResourceGraph::DescTag{}, rg, rescID); - const auto &traits = get(ResourceGraph::TraitsTag{}, rg, rescID); - // const PmrString *resName = &name; + auto evaluate = [&rag, &rescGraph, &relationGraph](RelationVert vert, bool forward) { + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); + return evaluateHeaviness(rag, rescGraph, ragVert, forward); + }; - Range range; - if (resourceDesc.dimension == ResourceDimension::BUFFER) { - range = BufferRange{0, resourceDesc.width}; + if (lhsVerts.size() == 2 || rhsVerts.size() == 2) { + /* + 1 ----------- 2 + \ __--/ + 3 --`` + no extra choice, only 1 - 3 - 2 + */ + const RelationVerts *shorterPath = lhsVerts.size() == 2 ? &lhsVerts : &rhsVerts; + remove_edge((*shorterPath)[0], (*shorterPath)[1], relationGraph); } else { - range = TextureRange{0, 1, 0, resourceDesc.mipLevels}; - } + // fist and last joint pass in this circuit don't get involved in reorder. + auto firstLhsNode = lhsVerts[1]; + auto lastLhsNode = lhsVerts[lhsVerts.size() - 2]; - CC_EXPECTS(rg.valueIndex.find(name) != rg.valueIndex.end()); - if (std::find(rag.resourceNames.begin(), rag.resourceNames.end(), name) == rag.resourceNames.end()) { - rag.resourceIndex.emplace(name, rescID); - rag.resourceNames.emplace_back(name); - } + const auto &lhsBackwardStatus = evaluate(firstLhsNode, false); + bool lhsAdjacentToStart = std::get<0>(lhsBackwardStatus); + const auto &lhsForwardStatus = evaluate(lastLhsNode, true); + bool lhsAdjacentToEnd = std::get<0>(lhsForwardStatus); - node.attachmentStatus.emplace_back(AccessStatus{ - rescID, - visibility, - access, - passType, - accessFlag, - usage, - range, - }); - return name; -} + auto firstRhsNode = rhsVerts[1]; + auto lastRhsNode = rhsVerts[rhsVerts.size() - 2]; -AccessVertex dependencyCheck(RAG &rag, AccessVertex curVertID, const ResourceGraph &rg, const ViewStatus &viewStatus) { - const auto &[name, passType, visibility, access, accessFlag, usage] = viewStatus; - auto &accessRecord = rag.accessRecord; + const auto &rhsBackwardStatus = evaluate(firstRhsNode, true); + bool rhsAdjacentToStart = std::get<0>(rhsBackwardStatus); + const auto &rhsForwardStatus = evaluate(lastRhsNode, false); + bool rhsAdjacentToEnd = std::get<0>(rhsForwardStatus); - bool readOnly = isReadOnlyAccess(accessFlag); + if (lhsAdjacentToStart || rhsAdjacentToEnd || lhsAdjacentToEnd || rhsAdjacentToStart) { + const RelationVerts *formerPath = &lhsVerts; + const RelationVerts *latterPath = &rhsVerts; + if (rhsAdjacentToStart || lhsAdjacentToEnd) { + swap(formerPath, latterPath); + } - AccessVertex lastVertID = INVALID_ID; - CC_EXPECTS(rag.resourceIndex.find(name) != rag.resourceIndex.end()); - auto resourceID = rag.resourceIndex[name]; - bool isExternalPass = get(get(ResourceGraph::TraitsTag{}, rg), resourceID).hasSideEffects(); - auto iter = accessRecord.find(resourceID); - if (iter == accessRecord.end()) { - accessRecord.emplace( - resourceID, - ResourceTransition{ - {}, - {curVertID, visibility, access, passType, accessFlag, usage, Range{}}}); - if (isExternalPass) { - rag.leafPasses[curVertID] = LeafStatus{true, access == gfx::MemoryAccessBit::READ_ONLY}; + remove_edge((*latterPath)[0], (*latterPath)[1], relationGraph); + remove_edge((*formerPath)[formerPath->size() - 2], (*formerPath)[formerPath->size() - 1], relationGraph); + + tryAddEdge((*formerPath)[formerPath->size() - 2], (*latterPath)[1], relationGraph); } - } else { - ResourceTransition &trans = iter->second; - auto &currAccessStatus = trans.currStatus; - auto lastReadOnly = isReadOnlyAccess(currAccessStatus.accessFlag) && (currAccessStatus.access == gfx::MemoryAccessBit::READ_ONLY); - if (readOnly && lastReadOnly) { - if (isExternalPass) { - // only external res will be manually record here, leaf pass with transient resource will be culled by default, - // those leaf passes with ALL read access on external(or with transients) res can be culled. - rag.leafPasses[curVertID].needCulling &= (access == gfx::MemoryAccessBit::READ_ONLY); - - // current READ, no WRITE before in this frame, it's expected to be external. - bool dirtyExternalRes = trans.lastStatus.vertID == INVALID_ID; - if (!dirtyExternalRes) { - tryAddEdge(EXPECT_START_ID, curVertID, rag); - if (rag.leafPasses.find(EXPECT_START_ID) != rag.leafPasses.end()) { - rag.leafPasses.erase(EXPECT_START_ID); - } - } - } else { - tryAddEdge(trans.lastStatus.vertID, curVertID, rag); - if (rag.leafPasses.find(trans.lastStatus.vertID) != rag.leafPasses.end()) { - rag.leafPasses.erase(trans.lastStatus.vertID); - } - } - trans.currStatus = {curVertID, visibility, access, passType, accessFlag, usage, Range{}}; - lastVertID = trans.lastStatus.vertID; - } else { - // avoid subpass self depends - if (trans.currStatus.vertID != curVertID) { - lastVertID = trans.currStatus.vertID; - trans.lastStatus = trans.currStatus; - trans.currStatus = {curVertID, visibility, access, passType, accessFlag, usage, Range{}}; - if (rag.leafPasses.find(trans.lastStatus.vertID) != rag.leafPasses.end()) { - rag.leafPasses.erase(trans.lastStatus.vertID); - } - if (rag.leafPasses.find(curVertID) != rag.leafPasses.end()) { - // only write into externalRes counts - if (isExternalPass) { - // same as above - rag.leafPasses[curVertID].needCulling &= (access == gfx::MemoryAccessBit::READ_ONLY); - } - } - } else { - trans.currStatus = {curVertID, visibility, trans.currStatus.access | access, passType, accessFlag, usage, Range{}}; + + assert(lhsVerts.size() >= 3 && rhsVerts.size() >= 3); + constexpr int64_t score = std::numeric_limits::lowest(); + ccstd::vector> candidateSections; + std::queue lhsSection; + for (size_t i = 1; i < lhsVerts.size(); ++i) { + auto tryE = edge(lhsVerts[i], lhsVerts[i - 1], relationGraphTc); + auto tryRE = edge(lhsVerts[i - 1], lhsVerts[i], relationGraphTc); + // check if original reachable + if (!tryE.second && !tryRE.second) { + remove_edge(lhsVerts[i - 1], lhsVerts[i], relationGraph); + candidateSections.emplace_back(lhsSection); + std::queue clearQ; + lhsSection.swap(clearQ); } - } - } - return lastVertID; -} + auto e = edge(lhsVerts[i], lhsVerts[i - 1], relationGraph); + // verts comes in order, so either real edge exist or logic edge is added. + CC_ASSERT(e.second); -gfx::ShaderStageFlagBit getVisibilityByDescName(const RenderGraph &renderGraph, const LGD &lgd, uint32_t passID, const PmrString &resName) { - auto iter = lgd.attributeIndex.find(resName); - if (iter == lgd.attributeIndex.end()) { - iter = lgd.constantIndex.find(resName); - if (iter == lgd.constantIndex.end()) { - // resource not in descriptor: eg. input or output attachment. - return gfx::ShaderStageFlagBit::NONE; + lhsSection.emplace(e.first); + } + if (candidateSections.empty()) { + // if this one is a tight edge(no logic edge, dependent from one to its next), + // keep this whole chain as a candidate. + remove_edge(lhsVerts[0], lhsVerts[1], relationGraph); + remove_edge(lhsVerts[lhsVerts.size() - 2], lhsVerts[lhsVerts.size() - 1], relationGraph); + candidateSections.emplace_back(std::move(lhsSection)); } - } - auto slotID = iter->second; - auto layoutName = get(RenderGraph::LayoutTag{}, renderGraph, passID); - auto layoutID = locate(LayoutGraphData::null_vertex(), layoutName, lgd); - const auto &layout = get(LayoutGraphData::LayoutTag{}, lgd, layoutID); - for (const auto &pair : layout.descriptorSets) { - for (const auto &block : pair.second.descriptorSetLayoutData.descriptorBlocks) { - for (const auto &descriptor : block.descriptors) { - if (descriptor.descriptorID.value == slotID.value) { - return block.visibility; - } + std::queue rhsSection; + for (size_t i = 1; i < rhsVerts.size(); ++i) { + auto tryE = edge(rhsVerts[i], rhsVerts[i - 1], relationGraphTc); + auto tryRE = edge(rhsVerts[i - 1], rhsVerts[i], relationGraphTc); + if (!tryE.second && !tryRE.second) { + remove_edge(rhsVerts[i - 1], rhsVerts[i], relationGraph); + candidateSections.emplace_back(rhsSection); + std::queue clearQ; + rhsSection.swap(clearQ); } + auto e = edge(rhsVerts[i], rhsVerts[i - 1], relationGraph); + // verts comes in order, so either real edge exist or logic edge is added. + CC_ASSERT(e.second); + rhsSection.emplace(e.first); } - } - - // unreachable - CC_EXPECTS(false); - return gfx::ShaderStageFlagBit::NONE; -}; - -bool checkRasterViews(const Graphs &graphs, uint32_t vertID, uint32_t passID, PassType passType, ResourceAccessNode &node, const RasterViewsMap &rasterViews) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - bool dependent = false; - for (const auto &pair : rasterViews) { - const auto &rasterView = pair.second; - auto access = toGfxAccess(rasterView.accessType); - gfx::ShaderStageFlagBit tryGotVis = getVisibilityByDescName(renderGraph, layoutGraphData, passID, pair.second.slotName); - tryGotVis |= pair.second.shaderStageFlags; - const auto &[vis, usage, accessFlag] = getResourceStatus(passType, pair.first, access, tryGotVis, resourceGraph, true); - ViewStatus viewStatus{pair.first, passType, vis, access, accessFlag, usage}; - addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - auto lastVertId = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, viewStatus); - if (lastVertId != INVALID_ID && lastVertId != vertID) { - tryAddEdge(lastVertId, vertID, resourceAccessGraph); - tryAddEdge(lastVertId, vertID, relationGraph); - dependent = true; + // lhs verts already put in. + if (candidateSections.size() == 1) { + remove_edge(rhsVerts[0], rhsVerts[1], relationGraph); + remove_edge(rhsVerts[rhsVerts.size() - 2], rhsVerts[rhsVerts.size() - 1], relationGraph); + candidateSections.emplace_back(std::move(rhsSection)); } - } - - // sort for vector intersection - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); - return dependent; -} + assert(candidateSections.size() >= 2); -bool checkComputeViews(const Graphs &graphs, uint32_t vertID, uint32_t passID, PassType passType, ResourceAccessNode &node, const ComputeViewsMap &computeViews) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - bool dependent = false; + ScoreMap scMap; + auto tailVert = lhsVerts[0]; + while (!candidateSections.empty()) { + int64_t lightest = std::numeric_limits::max(); + uint32_t index = 0; + for (size_t i = 0; i < candidateSections.size(); ++i) { + auto e = candidateSections[i].front(); + auto srcVert = source(e, relationGraph); + auto dstVert = target(e, relationGraph); + int64_t srcBackwardScore = 0; + int64_t dstForwardScore = 0; + if (scMap.find(srcVert) == scMap.end()) { + auto res = evaluate(srcVert, false); + srcBackwardScore = std::get<1>(res); + res = evaluate(srcVert, true); + auto srcForwardScore = std::get<1>(res); + scMap.emplace(srcVert, std::pair(srcBackwardScore, srcForwardScore)); + } else { + srcBackwardScore = std::get<0>(scMap.at(srcVert)); + } + if (scMap.find(dstVert) == scMap.end()) { + auto res = evaluate(dstVert, false); + dstForwardScore = std::get<1>(res); + res = evaluate(dstVert, true); + auto dstBackwardScore = std::get<1>(res); + scMap.emplace(dstVert, std::pair(dstBackwardScore, dstForwardScore)); + } else { + dstForwardScore = std::get<1>(scMap.at(dstVert)); + } - for (const auto &pair : computeViews) { - const auto &values = pair.second; - for (const auto &computeView : values) { - auto access = toGfxAccess(computeView.accessType); - gfx::ShaderStageFlagBit tryGotVis = gfx::ShaderStageFlagBit::NONE; - for (const auto &view : pair.second) { - tryGotVis |= getVisibilityByDescName(renderGraph, layoutGraphData, passID, view.name); - tryGotVis |= view.shaderStageFlags; + // we are in a simple path, so all the "input(this path)" resource of this path come from the first vertex, + // all the "output(this path)" come to the last vertex, other resources are "internally(this path)" produced and destroyed. + // so only input of first vertex and output of last vertex are taken into account. + // [simple path]: path without diverged edges. + auto score = dstForwardScore - srcBackwardScore; + if (lightest > score) { + lightest = score; + index = i; + } } - const auto &[vis, usage, accessFlag] = getResourceStatus(passType, pair.first, access, tryGotVis, resourceGraph, false); - ViewStatus viewStatus{pair.first, passType, vis, access, accessFlag, usage}; - addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - auto lastVertId = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, viewStatus); - if (lastVertId != INVALID_ID) { - tryAddEdge(lastVertId, vertID, resourceAccessGraph); - tryAddEdge(lastVertId, vertID, relationGraph); - dependent = true; + auto e = candidateSections[index].front(); + candidateSections[index].pop(); + if (candidateSections[index].empty()) { + auto iter = candidateSections.begin(); + std::advance(iter, index); + candidateSections.erase(iter); } + auto srcVert = source(e, relationGraph); + auto dstVert = target(e, relationGraph); + tryAddEdge(tailVert, srcVert, relationGraph); + tailVert = dstVert; } - } - - // sort for vector intersection - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); - - return dependent; -} -bool checkResolveResource(const Graphs &graphs, uint32_t vertID, uint32_t /*passID*/, ResourceAccessNode &node, const ccstd::pmr::vector &resolves) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - bool dependent = false; - for (const auto &pair : resolves) { - const auto &resolveTargetName = pair.target; - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex(resolveTargetName, resourceGraph)); - gfx::AccessFlags accessFlag = gfx::AccessFlags::COLOR_ATTACHMENT_WRITE; - gfx::TextureUsage usage = gfx::TextureUsage::COLOR_ATTACHMENT; - if (desc.format == gfx::Format::DEPTH_STENCIL) { - accessFlag = gfx::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE; - usage = gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT; - } - ViewStatus viewStatus{resolveTargetName, - PassType::RASTER, - gfx::ShaderStageFlags::FRAGMENT, - gfx::MemoryAccess::WRITE_ONLY, - accessFlag, usage}; - addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - auto lastVertId = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, viewStatus); - if (lastVertId != INVALID_ID) { - tryAddEdge(lastVertId, vertID, resourceAccessGraph); - tryAddEdge(lastVertId, vertID, relationGraph); - dependent = true; - } + tryAddEdge(tailVert, lhsVerts.back(), relationGraph); } - // sort for vector intersection - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); - - return dependent; } -void fillRenderPassInfo(gfx::LoadOp loadOp, gfx::StoreOp storeOp, AttachmentType attachmentType, gfx::RenderPassInfo &rpInfo, uint32_t index, const ResourceDesc &viewDesc, bool resolve) { - if (attachmentType != AttachmentType::DEPTH_STENCIL) { - auto &colorAttachment = rpInfo.colorAttachments[index]; - if (colorAttachment.format == gfx::Format::UNKNOWN) { - colorAttachment.format = viewDesc.format; - colorAttachment.loadOp = loadOp; - colorAttachment.storeOp = storeOp; - colorAttachment.sampleCount = viewDesc.sampleCount; - } else { - colorAttachment.storeOp = storeOp; - } - - } else { - auto &depthStencilAttachment = resolve ? - rpInfo.depthStencilResolveAttachment : - rpInfo.depthStencilAttachment; - if (depthStencilAttachment.format == gfx::Format::UNKNOWN) { - depthStencilAttachment.format = viewDesc.format; - depthStencilAttachment.depthLoadOp = loadOp; - depthStencilAttachment.depthStoreOp = storeOp; - depthStencilAttachment.stencilLoadOp = loadOp; - depthStencilAttachment.stencilStoreOp = storeOp; - depthStencilAttachment.sampleCount = viewDesc.sampleCount; - } else { - // TODO(Zeqiang): separate ds - depthStencilAttachment.depthStoreOp = storeOp; - depthStencilAttachment.stencilStoreOp = storeOp; - } - } -} +// return : can be further reduced? +bool reduce(const ResourceAccessGraph &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, RelationGraph &relationGraphTc, const CloseCircuit &circuit) { + auto checkPath = [&relationGraph](std::stack &vertices, RelationGraph::vertex_descriptor endVert, RelationVerts &stackTrace) { + bool simpleGraph = true; + while (!vertices.empty()) { + auto vert = vertices.top(); + vertices.pop(); + stackTrace.emplace_back(vert); -void processRasterPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + if (endVert == vert) { + break; + } - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - const auto &subpasses = pass.subpassGraph.subpasses; - bool hasSubpass = !subpasses.empty(); - auto &fgRenderpassInfo = resourceAccessGraph.rpInfos.emplace(vertID, FGRenderPassInfo{}).first->second; - auto &rpInfo = fgRenderpassInfo.rpInfo; - if (!hasSubpass) { - auto &rag = resourceAccessGraph; - auto size = std::count_if(pass.rasterViews.begin(), pass.rasterViews.end(), [](const auto &pair) { - return pair.second.attachmentType != AttachmentType::DEPTH_STENCIL; - }); - rpInfo.colorAttachments.resize(size); - fgRenderpassInfo.colorAccesses.resize(size); - PmrFlatMap> viewIndex(rag.get_allocator()); - for (const auto &[name, view] : pass.rasterViews) { - auto resIter = rag.resourceIndex.find(name); - gfx::AccessFlags prevAccess = resIter == rag.resourceIndex.end() ? gfx::AccessFlags::NONE : rag.accessRecord.at(resIter->second).currStatus.accessFlag; - viewIndex.emplace(std::piecewise_construct, std::forward_as_tuple(view.slotID), std::forward_as_tuple(name, prevAccess)); + if (out_degree(vert, relationGraph) > 1) { + simpleGraph = false; + break; + } + auto r = out_edges(vert, relationGraph); + for (auto rIter = r.first; rIter != r.second; ++rIter) { + auto dstID = target(*rIter, relationGraph); + vertices.push(dstID); + } + if (r.first == r.second) { + stackTrace.pop_back(); + } } + return simpleGraph; + }; + + // check if there is a sub branch on lhs + auto lhsEdges = circuit.first; + auto startVert = target(lhsEdges.first, relationGraph); + auto endVert = source(lhsEdges.second, relationGraph); - bool dependent = false; - dependent |= checkRasterViews(graphs, vertID, passID, PassType::RASTER, node, pass.rasterViews); - dependent |= checkComputeViews(graphs, vertID, passID, PassType::RASTER, node, pass.computeViews); + std::stack vertices; + vertices.emplace(startVert); - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); - } + RelationVerts lhsVisited; + auto branchStartVert = source(lhsEdges.first, relationGraph); + auto branchEndVert = target(lhsEdges.second, relationGraph); + lhsVisited.push_back(branchStartVert); + // check if there is a branch on lhs path + if (!checkPath(vertices, endVert, lhsVisited)) { + return false; + } + lhsVisited.push_back(branchEndVert); + // if it's a simple graph, lhs path must can be dfs to the end at the first time. + assert(vertices.empty()); - // initial layout(accessrecord.laststatus) and final layout(accessrecord.currstatus) can be filled here - for (const auto &[slotID, pair] : viewIndex) { - const auto &name = pair.first; - const auto resID = rag.resourceIndex.at(name); - const auto &view = pass.rasterViews.at(name); - const auto &viewDesc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - auto prevAccess = pair.second; - // TD:remove find - auto nodeIter = std::find_if(node.attachmentStatus.begin(), node.attachmentStatus.end(), [resID](const AccessStatus &status) { - return status.vertID == resID; - }); - auto nextAccess = nodeIter->accessFlag; + auto rhsEdges = circuit.second; + startVert = target(rhsEdges.first, relationGraph); + endVert = source(rhsEdges.second, relationGraph); + vertices.emplace(startVert); - if (rpInfo.subpasses.empty()) { - rpInfo.subpasses.emplace_back(); - } - auto &subpassInfo = rpInfo.subpasses.front(); - if (view.attachmentType != AttachmentType::DEPTH_STENCIL) { - if (view.attachmentType == AttachmentType::SHADING_RATE) { - subpassInfo.shadingRate = slotID; - } else { - if (view.accessType != AccessType::READ) { - subpassInfo.colors.emplace_back(slotID); - } - if (view.accessType != AccessType::WRITE) { - subpassInfo.inputs.emplace_back(slotID); - } - } - fgRenderpassInfo.colorAccesses[slotID].prevAccess = prevAccess; - fgRenderpassInfo.colorAccesses[slotID].nextAccess = nextAccess; - } else { - subpassInfo.depthStencil = pass.rasterViews.size() - 1; - fgRenderpassInfo.dsAccess.prevAccess = prevAccess; - fgRenderpassInfo.dsAccess.nextAccess = nextAccess; - } - fillRenderPassInfo(view.loadOp, view.storeOp, view.attachmentType, rpInfo, slotID, viewDesc, false); - fgRenderpassInfo.orderedViews.emplace_back(name); - } - } else { - auto colorSize = pass.rasterViews.size(); - bool hasDS = std::any_of(pass.rasterViews.begin(), pass.rasterViews.end(), [](const auto &pair) { - return pair.second.attachmentType == AttachmentType::DEPTH_STENCIL; - }); - colorSize -= hasDS; - const auto &subpasses = pass.subpassGraph.subpasses; - uint32_t count = 0; - const auto &resg = resourceGraph; - auto resolveNum = std::accumulate(subpasses.begin(), subpasses.end(), 0, [&resg](uint32_t initVal, const Subpass &subpass) { - auto iter = std::find_if(subpass.resolvePairs.begin(), subpass.resolvePairs.end(), [&resg](const auto &pair) { - auto resID = vertex(pair.target, resg); - const auto& desc = get(ResourceGraph::DescTag{}, resg, resID); - return desc.format == gfx::Format::DEPTH_STENCIL || desc.format == gfx::Format::DEPTH; - }); - return initVal + subpass.resolvePairs.size() - (iter != subpass.resolvePairs.end()); - }); - colorSize += resolveNum; - rpInfo.colorAttachments.resize(colorSize); - fgRenderpassInfo.colorAccesses.resize(colorSize); + RelationVerts rhsVisited; + rhsVisited.push_back(branchStartVert); + if (!checkPath(vertices, endVert, rhsVisited)) { + return false; } -} + rhsVisited.push_back(branchEndVert); -void processComputePass(const Graphs &graphs, uint32_t passID, const ComputePass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + // merge this circuit + // from + /* 2 - 3 - 4 + / \ + 1 8 + \ / + 5 - 6 - 7 - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - bool dependent = checkComputeViews(graphs, vertID, passID, PassType::COMPUTE, node, pass.computeViews); + to + 1 - A - B - 8 or 1 - B - A -8 depends on algorithm - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); - } -} + ${A} : 2 - 3 - 4 + ${B} : 5 - 6 - 7 + */ -uint32_t record(const ccstd::vector &indices) { - uint32_t res = 0; - for (auto attachmentIndex : indices) { - res |= 1 << attachmentIndex; - } - return res; -} + evaluateAndTryMerge(rag, rescGraph, relationGraph, relationGraphTc, lhsVisited, rhsVisited); -void extract(uint32_t val, ccstd::vector &preserves) { - uint32_t index = 0; - while (val) { - if (val & 0x1) { - preserves.emplace_back(index); - } - val = val >> 1; - ++index; - } + return true; } -void getPreserves(gfx::RenderPassInfo &rpInfo) { - std::stack stack; - for (auto &info : rpInfo.subpasses) { - stack.push(&info); - } +template +void applyRelation(RelationGraph &relationGraph, const TargetGraph &targetGraph) { + CC_EXPECTS(relationGraph.vertices.size() == targetGraph.vertices.size()); - uint32_t laterRead{0}; - while (!stack.empty()) { - auto *tail = stack.top(); - stack.pop(); + // remove all edges + for (auto vert : targetGraph.vertices) { + clear_in_edges(vert, targetGraph); + clear_out_edges(vert, targetGraph); + } - auto readRecord = record(tail->inputs); - auto writeRecord = record(tail->colors); - auto resolveRecord = record(tail->resolves); - auto shown = readRecord | writeRecord | resolveRecord; - auto needPreserve = (shown | laterRead) ^ shown; - extract(needPreserve, tail->preserves); - laterRead |= readRecord; + for (auto vert : relationGraph.vertices) { + auto inEdges = in_edges(vert, relationGraph); + for (auto e : makeRange(inEdges)) { + auto srcVert = source(e, relationGraph); + // auto checkEdge = edge(srcVert, vert, targetGraph); + add_edge(srcVert, vert, targetGraph); + } } } -void processRasterSubpass(const Graphs &graphs, uint32_t passID, const RasterSubpass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - const auto &obj = renderGraph.objects.at(passID); - const auto parentID = obj.parents.front().target; - const auto parentRagVert = resourceAccessGraph.passIndex.at(parentID); - const auto *parentPass = get_if(parentID, &renderGraph); - CC_EXPECTS(parentPass); - const auto &rag = resourceAccessGraph; - const auto &resg = resourceGraph; - const auto &uberPass = *parentPass; - - resourceAccessGraph.passIndex[passID] = parentRagVert; - - static const uint32_t ACCESS_TYPE_WEIGHT[] = {0, 1, 2}; - static const uint32_t ATTACHMENT_TYPE_WEIGHT[] = {0, 2, 1}; - - struct SubpassRasterViewSortKey { - uint32_t accessType; - uint32_t attachmentType; - std::string_view slotName; - uint32_t samplesReverseWeight; - }; - using RasterViewSortKey = std::tuple; - struct SubpassRasterViewData { - SubpassRasterViewSortKey sortKey; - std::string_view name; - gfx::AccessFlags access; - }; +void passReorder(FrameGraphDispatcher &fgDispatcher) { + auto *scratch = fgDispatcher.scratch; + const auto &renderGraph = fgDispatcher.renderGraph; + const auto &layoutGraph = fgDispatcher.layoutGraph; + auto &resourceGraph = fgDispatcher.resourceGraph; + auto &relationGraph = fgDispatcher.relationGraph; + auto &rag = fgDispatcher.resourceAccessGraph; - bool hasDS{false}; - ccstd::vector viewIndex; - for (const auto &[name, view] : pass.rasterViews) { - auto resIter = rag.resourceIndex.find(name); - const auto &resID = vertex(name, resourceGraph); - const auto &desc = get(ResourceGraph::DescTag{}, resg, resID); - gfx::AccessFlags prevAccess = resIter == rag.resourceIndex.end() ? gfx::AccessFlags::NONE : rag.accessRecord.at(resIter->second).currStatus.accessFlag; - viewIndex.emplace_back(SubpassRasterViewData{ - {ACCESS_TYPE_WEIGHT[static_cast(view.accessType)], ATTACHMENT_TYPE_WEIGHT[static_cast(view.attachmentType)], view.slotName, static_cast(desc.sampleCount)}, - name, - prevAccess, - }); - hasDS |= view.attachmentType == AttachmentType::DEPTH_STENCIL; + if (!fgDispatcher._accessGraphBuilt) { + const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + buildAccessGraph(graphs); + fgDispatcher._accessGraphBuilt = true; } - for (const auto &resolve : pass.resolvePairs) { - auto resIter = rag.resourceIndex.find(resolve.target); - gfx::AccessFlags prevAccess = resIter == rag.resourceIndex.end() ? gfx::AccessFlags::NONE : rag.accessRecord.at(resIter->second).currStatus.accessFlag; - viewIndex.emplace_back(SubpassRasterViewData{ - {ACCESS_TYPE_WEIGHT[static_cast(AccessType::WRITE)], ATTACHMENT_TYPE_WEIGHT[static_cast(AttachmentType::RENDER_TARGET)], "_", 0xFFFFFFFF}, - resolve.target, - prevAccess, - }); - } + { + // determine do mem saving how many times + RelationGraph relationGraphTc(fgDispatcher.get_allocator()); + boost::transitive_closure(relationGraph, relationGraphTc); - std::sort(viewIndex.begin(), viewIndex.end(), [](const SubpassRasterViewData &lhs, const SubpassRasterViewData &rhs) { - if (lhs.sortKey.samplesReverseWeight != rhs.sortKey.samplesReverseWeight) { - return lhs.sortKey.samplesReverseWeight < rhs.sortKey.samplesReverseWeight; - } - if (lhs.sortKey.accessType != rhs.sortKey.accessType) { - return lhs.sortKey.accessType < rhs.sortKey.accessType; - } - if (lhs.sortKey.attachmentType != rhs.sortKey.attachmentType) { - return lhs.sortKey.attachmentType < rhs.sortKey.attachmentType; - } - return lhs.sortKey.slotName < rhs.sortKey.slotName; - }); - - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, parentRagVert); - auto &fgRenderpassInfo = resourceAccessGraph.rpInfos.at(parentRagVert); - auto &rpInfo = fgRenderpassInfo.rpInfo; - auto &subpassInfo = rpInfo.subpasses.emplace_back(); - auto *lastNode = &node; - uint32_t subpassIndex = 0; - while (lastNode->nextSubpass) { - lastNode = lastNode->nextSubpass; - ++subpassIndex; - } - lastNode->nextSubpass = new ResourceAccessNode; - resourceAccessGraph.subpassIndex.emplace(passID, subpassIndex); - auto *head = lastNode->nextSubpass; - bool dependent{false}; - dependent |= checkRasterViews(graphs, parentRagVert, passID, PassType::RASTER, *head, pass.rasterViews); - dependent |= checkComputeViews(graphs, parentRagVert, passID, PassType::RASTER, *head, pass.computeViews); - dependent |= checkResolveResource(graphs, parentRagVert, passID, *head, pass.resolvePairs); - - if (!dependent) { - tryAddEdge(EXPECT_START_ID, parentRagVert, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, parentRagVert, relationGraph); - } - - if (!pass.resolvePairs.empty()) { - // ds resolve stores in depthStencilResolve - subpassInfo.resolves.resize(pass.rasterViews.size() - hasDS, gfx::INVALID_BINDING); - } - - uint32_t localSlot = 0; - bool dsAppeared{false}; - for (const auto &[sortKey, name, access] : viewIndex) { - const auto *const resName = name.data(); - auto findByResID = [&](const AccessStatus &status) { - return status.vertID == rag.resourceIndex.at(resName); - }; - auto iter = std::find_if(node.attachmentStatus.begin(), node.attachmentStatus.end(), findByResID); - - // TODO(Zeqiang): remove find - const auto &targetName = name; - auto resID = rag.resourceIndex.at(resName); - const auto &viewDesc = get(ResourceGraph::DescTag{}, resg, rag.resourceIndex.at(resName)); - - AttachmentType attachmentType{AttachmentType::RENDER_TARGET}; - AccessType accessType{AccessType::WRITE}; - gfx::LoadOp loadOp{gfx::LoadOp::DISCARD}; - gfx::StoreOp storeOp{gfx::StoreOp::STORE}; - - uint32_t slot = dsAppeared ? localSlot - 1 : localSlot; - // std::distance(uberPass.rasterViews.begin(), uberPass.rasterViews.find(resName)); - // slot = dsAppeared ? slot - 1 : slot; - /*if (attachmentType != AttachmentType::DEPTH_STENCIL) { - CC_ASSERT(uberPass.attachmentIndexMap.count(resName)); - slot = uberPass.attachmentIndexMap.at(resName); - }*/ - - // TD:remove find - auto nodeIter = std::find_if(head->attachmentStatus.begin(), head->attachmentStatus.end(), [resID](const AccessStatus &status) { - return status.vertID == resID; - }); - auto nextAccess = nodeIter->accessFlag; + CloseCircuits circuits; + std::vector crossEdges; + PassVisitor visitor(relationGraphTc, circuits); + auto colors = relationGraph.colors(scratch); + boost::depth_first_search(relationGraph, visitor, get(colors, relationGraph)); - auto resolveIter = std::find_if(pass.resolvePairs.begin(), pass.resolvePairs.end(), [&targetName](const ResolvePair &resolve) { - return strcmp(resolve.target.c_str(), targetName.data()) == 0; - }); - bool resolveView = resolveIter != pass.resolvePairs.end(); - if (resolveView) { - attachmentType = viewDesc.format == gfx::Format::DEPTH_STENCIL ? AttachmentType::DEPTH_STENCIL : AttachmentType::RENDER_TARGET; - if (attachmentType == AttachmentType::DEPTH_STENCIL) { - subpassInfo.depthStencilResolve = slot; - subpassInfo.depthResolveMode = gfx::ResolveMode::SAMPLE_ZERO; // resolveiter->mode; - subpassInfo.stencilResolveMode = gfx::ResolveMode::SAMPLE_ZERO; // resolveiter->mode1; - fgRenderpassInfo.dsResolveAccess.nextAccess = nextAccess; - } else { - auto indexIter = std::find(fgRenderpassInfo.orderedViews.begin(), fgRenderpassInfo.orderedViews.end(), resolveIter->source.c_str()); - auto srcIndex = indexIter == fgRenderpassInfo.orderedViews.end() ? fgRenderpassInfo.orderedViews.size() - : std::distance(fgRenderpassInfo.orderedViews.begin(), indexIter); - subpassInfo.resolves[srcIndex] = slot; - fgRenderpassInfo.colorAccesses[slot].nextAccess = nextAccess; - } - accessType = AccessType::WRITE; - } else { - const auto &view = pass.rasterViews.at(resName); - attachmentType = view.attachmentType; - accessType = view.accessType; - loadOp = view.loadOp; - storeOp = view.storeOp; - - if (attachmentType != AttachmentType::DEPTH_STENCIL) { - if (attachmentType == AttachmentType::SHADING_RATE) { - subpassInfo.shadingRate = slot; - } else { - if (accessType != AccessType::READ) { - subpassInfo.colors.emplace_back(slot); - } - if (accessType != AccessType::WRITE) { - subpassInfo.inputs.emplace_back(slot); - } - } - fgRenderpassInfo.colorAccesses[slot].nextAccess = nextAccess; + float percent = 0.0F; + uint32_t count = 0; + auto total = circuits.size(); + + float memsavePercent = 1.0F - fgDispatcher._paralellExecWeight; + for (auto iter = circuits.begin(); (iter != circuits.end()) && (percent < memsavePercent);) { + bool reduced = reduce(rag, resourceGraph, relationGraph, relationGraphTc, (*iter)); + if (reduced) { + ++count; + iter = circuits.erase(iter); + percent = count / static_cast(total); } else { - fgRenderpassInfo.dsAccess.nextAccess = nextAccess; - subpassInfo.depthStencil = rpInfo.colorAttachments.size(); - dsAppeared = true; + ++iter; } } - if (iter == node.attachmentStatus.end()) { - auto curIter = std::find_if(head->attachmentStatus.begin(), head->attachmentStatus.end(), findByResID); - node.attachmentStatus.emplace_back(*curIter); - auto prevAccess = access; - CC_ASSERT(head->attachmentStatus.size() > localSlot); - auto nextAccess = head->attachmentStatus[localSlot].accessFlag; + // topological sort + rag.topologicalOrder.clear(); + bool empty = relationGraph._vertices.empty(); + ScoreMap scoreMap; + RelationVerts candidates; + candidates.push_back(EXPECT_START_ID); - if (attachmentType == AttachmentType::DEPTH_STENCIL) { - if (resolveView) { - fgRenderpassInfo.dsResolveAccess.prevAccess = prevAccess; + std::vector candidateBuffer; + uint32_t coloredVerts = 0; + while (coloredVerts < relationGraph._vertices.size()) { + // decreasing order, pop back from vector, push into queue, then it's ascending order. + std::sort(candidates.begin(), candidates.end(), [&](RelationVert lhsVert, RelationVert rhsVert) { + int64_t lhsForwardScore{0}; + int64_t rhsForwardScore{0}; + int64_t lhsBackwardScore{0}; + int64_t rhsBackwardScore{0}; + if (scoreMap.find(lhsVert) == scoreMap.end()) { + auto lhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, lhsVert); + const auto &lhsForwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, true); + lhsForwardScore = get<1>(lhsForwardStatus); + const auto &lhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, false); + lhsBackwardScore = get<1>(lhsBackwardStatus); + scoreMap.emplace(lhsVert, std::pair{lhsBackwardScore, lhsForwardScore}); } else { - fgRenderpassInfo.dsAccess.prevAccess = prevAccess; + lhsBackwardScore = scoreMap[lhsVert].first; + lhsForwardScore = scoreMap[lhsVert].second; } - } else { - fgRenderpassInfo.colorAccesses[slot].prevAccess = prevAccess; - } - fgRenderpassInfo.orderedViews.emplace_back(resName); - } - fillRenderPassInfo(loadOp, storeOp, attachmentType, rpInfo, slot, viewDesc, resolveView); - fgRenderpassInfo.needResolve |= resolveView; - ++localSlot; - } - if (pass.subpassID == uberPass.subpassGraph.subpasses.size() - 1) { - getPreserves(rpInfo); - } -} - -void processComputeSubpass(const Graphs &graphs, uint32_t passID, const ComputeSubpass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - const auto &obj = renderGraph.objects.at(passID); - const auto parentID = obj.parents.front().target; - const auto parentRagVert = resourceAccessGraph.passIndex.at(parentID); - const auto *parentPass = get_if(parentID, &renderGraph); - CC_EXPECTS(parentPass); - const auto &rag = resourceAccessGraph; - const auto &resg = resourceGraph; - const auto &uberPass = *parentPass; - - resourceAccessGraph.passIndex[passID] = parentRagVert; + if (scoreMap.find(rhsVert) == scoreMap.end()) { + auto rhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, rhsVert); + const auto &rhsForwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, true); + rhsForwardScore = get<1>(rhsForwardStatus); + const auto &rhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, false); + rhsBackwardScore = get<1>(rhsBackwardStatus); + scoreMap.emplace(rhsVert, std::pair{rhsBackwardScore, rhsForwardScore}); + } else { + rhsBackwardScore = scoreMap[rhsVert].first; + rhsForwardScore = scoreMap[rhsVert].second; + } + return lhsBackwardScore - lhsForwardScore > rhsBackwardScore - rhsForwardScore; + }); - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, parentRagVert); + const auto vert = candidates.back(); + candidates.pop_back(); - auto *lastNode = &node; - while (lastNode->nextSubpass) { - lastNode = lastNode->nextSubpass; - } - lastNode->nextSubpass = new ResourceAccessNode; - auto *head = lastNode->nextSubpass; + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); + rag.topologicalOrder.emplace_back(ragVert); + if (!candidateBuffer.empty()) { + candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); + candidateBuffer.clear(); + } - bool dependent = checkComputeViews(graphs, parentRagVert, passID, PassType::COMPUTE, *head, pass.computeViews); + for (const auto nextGeneration : makeRange(out_edges(vert, relationGraph))) { + auto targetID = target(nextGeneration, relationGraph); + if (in_degree(targetID, relationGraph) == 1) { + candidateBuffer.emplace_back(targetID); + } + } - if (!dependent) { - tryAddEdge(EXPECT_START_ID, parentRagVert, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, parentRagVert, relationGraph); - } -} + auto deprecatedEdges = out_edges(vert, relationGraph); + for (auto iter = deprecatedEdges.first; iter < deprecatedEdges.second;) { + remove_edge(*iter, relationGraph); + deprecatedEdges = out_edges(vert, relationGraph); + iter = deprecatedEdges.first; + } -void processCopyPass(const Graphs &graphs, uint32_t passID, const CopyPass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + if (candidates.empty()) { + candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); + candidateBuffer.clear(); + } - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + coloredVerts++; + } - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - bool dependent = false; - for (const auto &pair : pass.copyPairs) { - auto sourceRange = Range{ - TextureRange{ - pair.sourceFirstSlice, - pair.sourcePlaneSlice, - pair.mipLevels, - pair.numSlices, - }}; - auto targetRange = Range{ - TextureRange{ - pair.targetFirstSlice, - pair.targetPlaneSlice, - pair.mipLevels, - pair.numSlices, - }}; - ResourceUsage srcUsage = gfx::TextureUsage::TRANSFER_SRC; - ViewStatus srcViewStatus{pair.source, PassType::COPY, defaultVisibility, gfx::MemoryAccessBit::READ_ONLY, gfx::AccessFlags::TRANSFER_READ, srcUsage}; - addCopyAccessStatus(resourceAccessGraph, resourceGraph, node, srcViewStatus, sourceRange); - ResourceUsage dstUsage = gfx::TextureUsage::TRANSFER_DST; - ViewStatus dstViewStatus{pair.target, PassType::COPY, defaultVisibility, gfx::MemoryAccessBit::WRITE_ONLY, gfx::AccessFlags::TRANSFER_WRITE, dstUsage}; - addCopyAccessStatus(resourceAccessGraph, resourceGraph, node, dstViewStatus, targetRange); - - uint32_t lastVertSrc = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, srcViewStatus); - if (lastVertSrc != INVALID_ID) { - tryAddEdge(lastVertSrc, vertID, resourceAccessGraph); - tryAddEdge(lastVertSrc, rlgVertID, relationGraph); - dependent = true; + // remove all edges + for (auto vert : makeRange(vertices(rag))) { + clear_in_edges(vert, rag); + clear_out_edges(vert, rag); } - uint32_t lastVertDst = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, dstViewStatus); - if (lastVertDst != INVALID_ID) { - tryAddEdge(lastVertDst, vertID, resourceAccessGraph); - tryAddEdge(lastVertDst, rlgVertID, relationGraph); - dependent = true; + + // apply relation + for (auto rlgVert : makeRange(vertices(relationGraph))) { + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); + auto inEdges = in_edges(rlgVert, relationGraph); + for (auto e : makeRange(inEdges)) { + auto srcRlgVert = source(e, relationGraph); + auto srcRagVert = get(RelationGraph::DescIDTag{}, relationGraph, srcRlgVert); + add_edge(srcRagVert, ragVert, rag); + } } } - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); - } - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); } -void processRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); +#pragma endregion PASS_REORDER - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - bool dependent = checkComputeViews(graphs, vertID, passID, PassType::RAYTRACE, node, pass.computeViews); +void memoryAliasing(FrameGraphDispatcher &fgDispatcher) { +} - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); +#pragma region assisstantFuncDefinition +template +bool tryAddEdge(uint32_t srcVertex, uint32_t dstVertex, Graph &graph) { + auto e = edge(srcVertex, dstVertex, graph); + if (!e.second) { + auto res = add_edge(srcVertex, dstVertex, graph); + CC_ENSURES(res.second); + return true; } + return false; +} + +bool isTransitionStatusDependent(const AccessStatus &lhs, const AccessStatus &rhs) { + return !(isReadOnlyAccess(lhs.accessFlag) && isReadOnlyAccess(rhs.accessFlag)); } #pragma endregion assisstantFuncDefinition diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 23fdda466bc..7e631e10b57 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -35,6 +35,7 @@ #include "RenderGraphGraphs.h" #include "RenderGraphTypes.h" #include "RenderingModule.h" +#include "NativeRenderGraphUtils.h" #include "cocos/renderer/gfx-base/GFXBarrier.h" #include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/gfx-base/GFXDescriptorSetLayout.h" @@ -70,7 +71,6 @@ struct RenderGraphVisitorContext { const RenderGraph& g; ResourceGraph& resourceGraph; const FrameGraphDispatcher& fgd; - const FrameGraphDispatcher::BarrierMap& barrierMap; const ccstd::pmr::vector& validPasses; gfx::Device* device = nullptr; gfx::CommandBuffer* cmdBuff = nullptr; @@ -164,145 +164,24 @@ gfx::GeneralBarrier* getGeneralBarrier(gfx::Device* device, const RasterView& vi return nullptr; } +ResourceGraph::vertex_descriptor getResourceID(const ccstd::pmr::string& name, const FrameGraphDispatcher& fgd) { + return fgd.realResourceID(name); +} + PersistentRenderPassAndFramebuffer createPersistentRenderPassAndFramebuffer( RenderGraphVisitorContext& ctx, const RasterPass& pass, - boost::container::pmr::memory_resource* scratch) { + boost::container::pmr::memory_resource* /*scratch*/) { auto& resg = ctx.resourceGraph; PersistentRenderPassAndFramebuffer data(pass.get_allocator()); - gfx::RenderPassInfo rpInfo{}; - - gfx::FramebufferInfo fbInfo{ - data.renderPass, - }; - fbInfo.colorTextures.reserve(pass.rasterViews.size()); - - PmrFlatSet set(scratch); - auto fillFrameBufferInfo = [&](const ccstd::vector& passViews, bool hasResolve) { - std::ignore = hasResolve; - const auto& uberPass = pass; - auto numTotalAttachments = static_cast(passViews.size()); - - // uint32_t dsvCount = 0; - uint32_t index = 0; - for (const auto& nameIn : passViews) { - const char* name = nameIn.c_str(); - bool colorLikeView{true}; - bool dsResolveAttachment{false}; - auto clearColor = gfx::Color{}; - auto iter = pass.rasterViews.find(name); - if(iter != pass.rasterViews.end()) { - const auto& view = iter->second; - colorLikeView = view.attachmentType == AttachmentType::RENDER_TARGET || view.attachmentType == AttachmentType::SHADING_RATE; - clearColor = view.clearColor; - } else { - // resolves - const auto resID = vertex(name, ctx.resourceGraph); - const auto& desc = get(ResourceGraph::DescTag{}, ctx.resourceGraph, resID); - CC_ASSERT(hasResolve && desc.sampleCount == gfx::SampleCount::X1); - colorLikeView = desc.format != gfx::Format::DEPTH_STENCIL && desc.format != gfx::Format::DEPTH; - dsResolveAttachment = !colorLikeView; - } - - if (colorLikeView) { // RenderTarget - data.clearColors.emplace_back(clearColor); - - auto resID = findVertex(name, resg); - visitObject( - resID, resg, - [&](const ManagedResource& res) { - std::ignore = res; - CC_EXPECTS(false); - }, - [&](const ManagedBuffer& res) { - std::ignore = res; - CC_EXPECTS(false); - }, - [&](const ManagedTexture& tex) { - CC_EXPECTS(tex.texture); - fbInfo.colorTextures.emplace_back(tex.texture); - }, - [&](const IntrusivePtr& res) { - std::ignore = res; - CC_EXPECTS(false); - }, - [&](const IntrusivePtr& tex) { - fbInfo.colorTextures.emplace_back(tex); - }, - [&](const IntrusivePtr& fb) { - CC_EXPECTS(fb->getColorTextures().size() == 1); - CC_EXPECTS(fb->getColorTextures().at(0)); - fbInfo.colorTextures.emplace_back(fb->getColorTextures()[index]); - // render window attaches a depthStencil by default, which may differs from renderpassInfo here. - // data.framebuffer = fb; - }, - [&](const RenderSwapchain& sc) { - fbInfo.colorTextures.emplace_back(sc.swapchain->getColorTexture()); - }, - [&](const FormatView& view) { - // TODO(zhouzhenglong): add ImageView support - std::ignore = view; - CC_EXPECTS(false); - }, - [&](const SubresourceView& view) { - // TODO(zhouzhenglong): add ImageView support - std::ignore = view; - CC_EXPECTS(false); - }); - } else { // DepthStencil - if (!dsResolveAttachment) { - data.clearDepth = clearColor.x; - data.clearStencil = static_cast(clearColor.y); - } + auto [rpInfo, fbInfo, clearColors, clearDepth, clearStencil] = ctx.fgd.getRenderPassAndFrameBuffer(ctx.currentInFlightPassID, resg); - auto &dsAttachment = dsResolveAttachment ? fbInfo.depthStencilResolveTexture : fbInfo.depthStencilTexture; - - auto resID = findVertex(name, resg); - visitObject( - resID, resg, - [&](const ManagedTexture& tex) { - CC_EXPECTS(tex.texture); - dsAttachment = tex.texture.get(); - }, - [&](const IntrusivePtr& tex) { - dsAttachment = tex.get(); - }, - [&](const FormatView& view) { - std::ignore = view; - CC_EXPECTS(false); - }, - [&](const SubresourceView& view) { - std::ignore = view; - CC_EXPECTS(false); - }, - [](const auto& /*unused*/) { - CC_EXPECTS(false); - }); - } - ++index; - } - }; - - const auto passID = ctx.currentInFlightPassID; - const auto ragVertID = ctx.fgd.resourceAccessGraph.passIndex.at(passID); - if (pass.subpassGraph.subpasses.empty()) { - const auto numInputs = getRasterPassInputCount(pass); - const auto numColors = getRasterPassOutputCount(pass); - - // persistent cache - data.clearColors.reserve(numColors); - const auto& fgdRpInfo = ctx.fgd.resourceAccessGraph.rpInfos.at(ragVertID); - rpInfo = fgdRpInfo.rpInfo; - fillFrameBufferInfo(fgdRpInfo.orderedViews, false); - - } else { - const auto& fgdRpInfo = ctx.fgd.resourceAccessGraph.rpInfos.at(ragVertID); - rpInfo = fgdRpInfo.rpInfo; - fillFrameBufferInfo(fgdRpInfo.orderedViews, fgdRpInfo.needResolve); - } - CC_ENSURES(rpInfo.colorAttachments.size() == data.clearColors.size()); + // CC_ENSURES(rpInfo.colorAttachments.size() == data.clearColors.size()); CC_ENSURES(rpInfo.colorAttachments.size() == fbInfo.colorTextures.size()); + data.clearColors = std::move(clearColors); + data.clearDepth = clearDepth; + data.clearStencil = clearStencil; data.renderPass = ctx.device->createRenderPass(rpInfo); fbInfo.renderPass = data.renderPass; data.framebuffer = ctx.device->createFramebuffer(fbInfo); @@ -660,28 +539,23 @@ gfx::DescriptorSet* initDescriptorSet( } break; case DescriptorTypeOrder::INPUT_ATTACHMENT: { - for (auto d : block.descriptors) { - CC_EXPECTS(d.count == 1); - auto iter = resourceIndex.find(d.descriptorID); - if (iter != resourceIndex.end()) { - // render graph textures - auto* texture = resg.getTexture(iter->second); - gfx::AccessFlags access = gfx::AccessFlagBit::NONE; - if (accessNode != nullptr) { - auto accIter = std::find_if( - accessNode->attachmentStatus.begin(), accessNode->attachmentStatus.end(), - [iter](const AccessStatus& status) { - return status.vertID == iter->second; - }); - access = accIter != accessNode->attachmentStatus.end() ? accIter->accessFlag : gfx::AccessFlagBit::NONE; - } - - CC_ENSURES(texture); - newSet->bindTexture(bindID, texture, 0, access); + for (const auto& [descID, resID] : resourceIndex) { + std::ignore = descID; + // render graph textures + auto* texture = resg.getTexture(resID); + gfx::AccessFlags access = gfx::AccessFlagBit::NONE; + if (accessNode != nullptr) { + // whole access only now. + auto parentID = parent(resID, resg); + parentID = parentID == ResourceGraph::null_vertex() ? resID : parentID; + const auto& resName = get(ResourceGraph::NameTag{}, resg, parentID); + access = accessNode->resourceStatus.at(resName).accessFlag; } - bindID += d.count; - } + CC_ENSURES(texture); + newSet->bindTexture(bindID, texture, 0, access); + bindID += 1; + } }; break; default: @@ -908,26 +782,6 @@ void submitProfilerCommands( cmdBuff->draw(ia); } -PmrFlatMap -buildResourceIndex( - const ResourceGraph& resg, - const LayoutGraphData& lg, - const PmrTransparentMap>& computeViews, - boost::container::pmr::memory_resource* scratch) { - PmrFlatMap resourceIndex(scratch); - resourceIndex.reserve(computeViews.size() * 2); - for (const auto& [resName, computeViews] : computeViews) { - const auto resID = vertex(resName, resg); - for (const auto& computeView : computeViews) { - const auto& name = computeView.name; - CC_EXPECTS(!name.empty()); - const auto nameID = lg.attributeIndex.at(name); - resourceIndex.emplace(nameID, resID); - } - } - return resourceIndex; -} - const PmrTransparentMap>& getComputeViews(RenderGraph::vertex_descriptor passID, const RenderGraph& rg) { if (holds(passID, rg)) { @@ -1073,8 +927,7 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { } // build pass resources - const auto& resourceIndex = buildResourceIndex( - ctx.resourceGraph, ctx.lg, computeViews, ctx.scratch); + const auto& resourceIndex = ctx.fgd.buildDescriptorIndex(computeViews, ctx.scratch); // populate set auto& set = iter->second; @@ -1106,8 +959,7 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { } // build pass resources - const auto& resourceIndex = buildResourceIndex( - ctx.resourceGraph, ctx.lg, computeViews, ctx.scratch); + const auto& resourceIndex = ctx.fgd.buildDescriptorIndex(computeViews, ctx.scratch); // find scene resource const auto* const sceneResource = getFirstSceneResource(vertID); @@ -1148,7 +1000,6 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { const auto& subpass = get(RasterSubpassTag{}, vertID, ctx.g); // render pass const auto& layoutName = get(RenderGraph::LayoutTag{}, ctx.g, vertID); - auto parentLayoutID = ctx.currentPassLayoutID; auto layoutID = parentLayoutID; if (!layoutName.empty()) { @@ -1169,35 +1020,12 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { return; } - // build pass resources - /* const auto& resourceIndex = buildResourceIndex( - ctx.resourceGraph, ctx.lg, subpass.computeViews, ctx.scratch);*/ - PmrFlatMap resourceIndex(ctx.scratch); - - resourceIndex.reserve(subpass.rasterViews.size() * 2); - for (const auto& [resName, rasterView] : subpass.rasterViews) { - const auto resID = vertex(resName, ctx.resourceGraph); - auto ragId = ctx.fgd.resourceAccessGraph.passIndex.at(vertID); - const auto& attachments = ctx.fgd.resourceAccessGraph.access[ragId].attachmentStatus; - auto resIter = std::find_if(attachments.begin(), attachments.end(), [resID](const AccessStatus& status) { - return status.vertID == resID; - }); - - auto slotName = rasterView.slotName; - if (rasterView.accessType == AccessType::READ || rasterView.accessType == AccessType::READ_WRITE) { - slotName.insert(0, "__in"); - } - auto iter = ctx.lg.attributeIndex.find(slotName); - if (iter != ctx.lg.attributeIndex.end()) { - resourceIndex.emplace(iter->second, resID); - } - } - + const auto& resourceIndex = ctx.fgd.buildDescriptorIndex(subpass.computeViews, subpass.rasterViews, ctx.scratch); // populate set auto& set = iter->second; const auto& user = get(RenderGraph::DataTag{}, ctx.g, vertID); auto& node = ctx.context.layoutGraphResources.at(layoutID); - const auto& accessNode = ctx.fgd.getAttachmentStatus(vertID); + const auto& accessNode = ctx.fgd.getAccessNode(vertID); auto* perPassSet = initDescriptorSet( ctx.resourceGraph, @@ -1258,25 +1086,15 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { textureBarriers.data(), textures.data(), static_cast(textureBarriers.size())); } void frontBarriers(RenderGraph::vertex_descriptor vertID) const { - auto iter = ctx.fgd.resourceAccessGraph.passIndex.find(vertID); - if (iter == ctx.fgd.resourceAccessGraph.passIndex.end()) { - return; - } - const auto& nodeID = iter->second; - auto iter2 = ctx.barrierMap.find(nodeID); - if (iter2 != ctx.barrierMap.end()) { - submitBarriers(iter2->second.blockBarrier.frontBarriers); + const auto& barrier = ctx.fgd.getBarrier(vertID); + if (!barrier.frontBarriers.empty()) { + submitBarriers(barrier.frontBarriers); } } void rearBarriers(RenderGraph::vertex_descriptor vertID) const { - auto iter = ctx.fgd.resourceAccessGraph.passIndex.find(vertID); - if (iter == ctx.fgd.resourceAccessGraph.passIndex.end()) { - return; - } - const auto& nodeID = iter->second; - auto iter2 = ctx.barrierMap.find(nodeID); - if (iter2 != ctx.barrierMap.end()) { - submitBarriers(iter2->second.blockBarrier.rearBarriers); + const auto& barrier = ctx.fgd.getBarrier(vertID); + if (!barrier.rearBarriers.empty()) { + submitBarriers(barrier.rearBarriers); } } void tryBindPerPassDescriptorSet(RenderGraph::vertex_descriptor vertID) const { @@ -1352,6 +1170,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { if (subpass.subpassID) { ctx.cmdBuff->nextSubpass(); } + //ctx.cmdBuff->setViewport(subpass); tryBindPerPassDescriptorSet(vertID); ctx.subpassIndex = subpass.subpassID; // noop @@ -1750,41 +1569,34 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } void end(const gfx::Viewport& pass, RenderGraph::vertex_descriptor vertID) const { } + + void mountResource(const ccstd::pmr::string& name) const { + auto resID = ctx.fgd.resourceAccessGraph.resourceIndex.at(name); + CC_EXPECTS(resID != ResourceGraph::null_vertex()); + ctx.resourceGraph.mount(ctx.device, resID); + } void mountResources(const Subpass& pass) const { - auto& resg = ctx.resourceGraph; // mount managed resources for (const auto& [name, view] : pass.rasterViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } for (const auto& resolve : pass.resolvePairs) { - auto resID = findVertex(resolve.target, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(resolve.target); } } void mountResources(const RasterPass& pass) const { - auto& resg = ctx.resourceGraph; // mount managed resources for (const auto& [name, view] : pass.rasterViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } - for (const auto& subpass : pass.subpassGraph.subpasses) { mountResources(subpass); } @@ -1794,9 +1606,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } } @@ -1804,9 +1614,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } } @@ -1814,9 +1622,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } } @@ -1824,12 +1630,8 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& pair : pass.resolvePairs) { - const auto& srcID = findVertex(pair.source, resg); - CC_EXPECTS(srcID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, srcID); - const auto& dstID = findVertex(pair.target, resg); - CC_EXPECTS(dstID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, dstID); + mountResource(pair.source); + mountResource(pair.target); } } @@ -1837,17 +1639,11 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& pair : pass.copyPairs) { - const auto& srcID = findVertex(pair.source, resg); - CC_EXPECTS(srcID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, srcID); - const auto& dstID = findVertex(pair.target, resg); - CC_EXPECTS(dstID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, dstID); + mountResource(pair.source); + mountResource(pair.target); } for (const auto& pair : pass.uploadPairs) { - const auto& dstID = findVertex(pair.target, resg); - CC_EXPECTS(dstID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, dstID); + mountResource(pair.target); } } @@ -2223,7 +2019,7 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { RenderGraphVisitorContext ctx{ ppl.nativeContext, lg, rg, ppl.resourceGraph, - fgd, fgd.barrierMap, + fgd, validPasses, ppl.device, submit.primaryCommandBuffer, &ppl, diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index ff89a8cd6dc..f747e151f36 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -42,6 +42,50 @@ namespace cc { namespace render { +template +void addSubresourceNode(ResourceGraph::vertex_descriptor v, const ccstd::string &name, ResourceGraph &resg); + +template <> +void addSubresourceNode(ResourceGraph::vertex_descriptor v, const ccstd::string &name, ResourceGraph &resg) { + SubresourceView view{ + nullptr, + gfx::Format::DEPTH_STENCIL, + 0, 1, 0, 1, 0, 1}; + + auto desc = get(ResourceGraph::DescTag{}, resg, v); + auto traits = get(ResourceGraph::TraitsTag{}, resg, v); + auto samplerInfo = get(ResourceGraph::SamplerTag{}, resg, v); + + ccstd::string depthName{name}; + depthName += "/"; + depthName += DEPTH_PLANE_NAME; + auto depthID = addVertex( + SubresourceViewTag{}, + std::forward_as_tuple(depthName.c_str()), + std::forward_as_tuple(desc), + std::forward_as_tuple(traits.residency), + std::forward_as_tuple(), + std::forward_as_tuple(samplerInfo), + std::forward_as_tuple(view), + resg, + v); + + view.firstPlane = 1; + ccstd::string stencilName{name}; + stencilName += "/"; + stencilName += STENCIL_PLANE_NAME; + auto stencilID = addVertex( + SubresourceViewTag{}, + std::forward_as_tuple(stencilName.c_str()), + std::forward_as_tuple(desc), + std::forward_as_tuple(traits.residency), + std::forward_as_tuple(), + std::forward_as_tuple(samplerInfo), + std::forward_as_tuple(view), + resg, + v); +} + NativePipeline::NativePipeline(const allocator_type &alloc) noexcept : device(gfx::Device::getInstance()), globalDSManager(std::make_unique()), @@ -194,7 +238,8 @@ uint32_t NativePipeline::addDepthStencil(const ccstd::string &name, gfx::Format samplerInfo.magFilter = gfx::Filter::POINT; samplerInfo.minFilter = gfx::Filter::POINT; samplerInfo.mipFilter = gfx::Filter::NONE; - return addVertex( + + auto resID = addVertex( ManagedTextureTag{}, std::forward_as_tuple(name.c_str()), std::forward_as_tuple(desc), @@ -203,6 +248,9 @@ uint32_t NativePipeline::addDepthStencil(const ccstd::string &name, gfx::Format std::forward_as_tuple(samplerInfo), std::forward_as_tuple(), resourceGraph); + + addSubresourceNode(resID, name, resourceGraph); + return resID; } uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimension dimension, diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 528c95d5ce7..91c9dcf73b4 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -298,6 +298,21 @@ void addRasterViewImpl( auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); const auto slotID = getSlotID(pass, name, attachmentType); CC_EXPECTS(subpass.rasterViews.size() == subpassData.rasterViews.size()); + auto nameIter = subpassData.rasterViews.find(name); + + if (nameIter != subpassData.rasterViews.end()) { + auto &view = subpass.rasterViews.at(name.data()); + if (!defaultAttachment(slotName)) { + nameIter->second.slotName = slotName; + view.slotName = slotName; + } + if (!defaultAttachment(slotName1)) { + nameIter->second.slotName1 = slotName1; + view.slotName1 = slotName1; + } + return; + } + { auto res = subpassData.rasterViews.emplace( std::piecewise_construct, @@ -321,6 +336,7 @@ void addRasterViewImpl( std::forward_as_tuple(name), std::forward_as_tuple( ccstd::pmr::string(slotName, subpassData.get_allocator()), + ccstd::pmr::string(slotName1, subpassData.get_allocator()), accessType, attachmentType, loadOp, @@ -533,18 +549,18 @@ void NativeRenderSubpassBuilderImpl::setShowStatistics(bool enable) { void NativeMultisampleRenderSubpassBuilder::resolveRenderTarget( const ccstd::string &source, const ccstd::string &target) { // NOLINT(bugprone-easily-swappable-parameters) auto &subpass = get(RasterSubpassTag{}, nodeID, *renderGraph); - + auto parentID = parent(nodeID, *renderGraph); auto &pass = get(RasterPassTag{}, parentID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); - + subpass.resolvePairs.emplace_back( ccstd::pmr::string(source.data(), renderGraph->get_allocator()), ccstd::pmr::string(target.data(), renderGraph->get_allocator()), ResolveFlags::COLOR, gfx::ResolveMode::AVERAGE, gfx::ResolveMode::NONE); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } @@ -559,7 +575,7 @@ void NativeMultisampleRenderSubpassBuilder::resolveDepthStencil( if (stencilMode != gfx::ResolveMode::NONE) { flags |= ResolveFlags::STENCIL; } - + auto parentID = parent(nodeID, *renderGraph); auto &pass = get(RasterPassTag{}, parentID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); @@ -570,7 +586,7 @@ void NativeMultisampleRenderSubpassBuilder::resolveDepthStencil( flags, depthMode, stencilMode); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } @@ -1137,17 +1153,17 @@ void NativeMultisampleRenderPassBuilder::setShowStatistics(bool enable) { void NativeMultisampleRenderPassBuilder::resolveRenderTarget( const ccstd::string &source, const ccstd::string &target) { // NOLINT(bugprone-easily-swappable-parameters) auto &subpass = get(RasterSubpassTag{}, subpassID, *renderGraph); - + auto &pass = get(RasterPassTag{}, nodeID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); - + subpass.resolvePairs.emplace_back( ccstd::pmr::string(source.data(), renderGraph->get_allocator()), ccstd::pmr::string(target.data(), renderGraph->get_allocator()), ResolveFlags::COLOR, gfx::ResolveMode::AVERAGE, gfx::ResolveMode::NONE); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } @@ -1162,7 +1178,7 @@ void NativeMultisampleRenderPassBuilder::resolveDepthStencil( if (stencilMode != gfx::ResolveMode::NONE) { flags |= ResolveFlags::STENCIL; } - + auto &pass = get(RasterPassTag{}, nodeID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); @@ -1172,7 +1188,7 @@ void NativeMultisampleRenderPassBuilder::resolveDepthStencil( flags, depthMode, stencilMode); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h index 18858869210..bf1ff547408 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h @@ -211,6 +211,19 @@ void addSubpassComputeViewImpl( subpassData.computeViews.find(std::string_view{name})->second.size()); } +inline bool defaultAttachment(std::string_view slotName) { + return slotName.empty() || slotName == "_"; +} + +static constexpr std::string_view DEPTH_PLANE_NAME = "depth"; +static constexpr std::string_view STENCIL_PLANE_NAME = "stencil"; +static constexpr std::string_view CUBE_TOP_NAME = "Top"; +static constexpr std::string_view CUBE_BOTTOM_NAME = "Bottom"; +static constexpr std::string_view CUBE_FRONT_NAME = "Front"; +static constexpr std::string_view CUBE_REAR_NAME = "Rear"; +static constexpr std::string_view CUBE_LEFT_NAME = "Left"; +static constexpr std::string_view CUBE_RIGHT_NAME = "Right"; + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 984e215a9ad..7b1b3e22726 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -22,10 +22,12 @@ THE SOFTWARE. ****************************************************************************/ +#include #include "NativePipelineTypes.h" #include "RenderGraphGraphs.h" #include "RenderGraphTypes.h" #include "cocos/renderer/gfx-base/GFXDevice.h" +#include "details/GraphView.h" #include "details/Range.h" #include "gfx-base/GFXDef-common.h" #include "pipeline/custom/RenderCommonFwd.h" @@ -168,6 +170,23 @@ gfx::TextureInfo getTextureInfo(const ResourceDesc& desc, bool bCube = false) { }; } +gfx::TextureViewInfo getTextureViewInfo(const SubresourceView& subresView, const ResourceDesc& desc, bool bCube = false) { + using namespace gfx; // NOLINT(google-build-using-namespace) + + const auto& textureInfo = getTextureInfo(desc, bCube); + + return { + nullptr, + textureInfo.type, + subresView.format, + subresView.indexOrFirstMipLevel, + subresView.numMipLevels, + subresView.firstArraySlice, + subresView.numArraySlices, + subresView.firstPlane, + subresView.numPlanes, + }; +} } // namespace bool ManagedTexture::checkResource(const ResourceDesc& desc) const { @@ -233,7 +252,7 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(queue.swapchain); std::ignore = queue; }, - [&](const FormatView& view) { // NOLINT(misc-no-recursion) + [&](const FormatView& view) { std::ignore = view; auto parentID = parent(vertID, resg); CC_EXPECTS(parentID != resg.null_vertex()); @@ -243,10 +262,9 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); - mount(device, parentID); + mount(device, parentID); // NOLINT(misc-no-recursion) }, - [&](const SubresourceView& view) { // NOLINT(misc-no-recursion) - std::ignore = view; + [&](SubresourceView& view) { // NOLINT(misc-no-recursion) auto parentID = parent(vertID, resg); CC_EXPECTS(parentID != resg.null_vertex()); while (resg.isTextureView(parentID)) { @@ -255,7 +273,13 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); - mount(device, parentID); + auto* parentTexture = resg.getTexture(parentID); + const auto& desc = get(ResourceGraph::DescTag{}, resg, vertID); + if (!view.textureView) { + auto textureViewInfo = getTextureViewInfo(view, desc); + textureViewInfo.texture = parentTexture; + view.textureView = device->createTexture(textureViewInfo); + } }); } @@ -362,8 +386,7 @@ gfx::Texture* ResourceGraph::getTexture(vertex_descriptor resID) { }, [&](const SubresourceView& view) { // TODO(zhouzhenglong): add ImageView support - std::ignore = view; - CC_EXPECTS(false); + texture = view.textureView; }, [&](const auto& buffer) { std::ignore = buffer; diff --git a/native/cocos/renderer/pipeline/custom/test/test.h b/native/cocos/renderer/pipeline/custom/test/test.h index ed8f44f5eec..f329ac731f4 100644 --- a/native/cocos/renderer/pipeline/custom/test/test.h +++ b/native/cocos/renderer/pipeline/custom/test/test.h @@ -60,7 +60,6 @@ using framegraph::PassBarrierPair; using framegraph::ResourceBarrier; using RasterViews = PmrTransparentMap; using ComputeViews = PmrTransparentMap>; -using BarrierMap = FrameGraphDispatcher::BarrierMap; static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescInfo, const LayoutInfo &layoutInfo, RenderGraph &renderGraph, ResourceGraph &rescGraph, LayoutGraphData &layoutGraphData) { for (const auto &resc : rescInfo) { @@ -104,6 +103,7 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn auto addRasterNode = [&](const vector>> &subpasses, uint32_t count, uint32_t passID) { const ccstd::string name = "pass" + std::to_string(passID); const auto vertexID = add_vertex(renderGraph, RasterPassTag{}, name.c_str()); + renderGraph.sortedVertices.emplace_back(vertexID); auto &raster = get(RasterPassTag{}, vertexID, renderGraph); auto &subpassGraph = raster.subpassGraph; @@ -195,6 +195,7 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn const ccstd::string name = "pass" + std::to_string(passCount++); const auto vertexID = add_vertex(renderGraph, ComputeTag{}, name.c_str()); + renderGraph.sortedVertices.emplace_back(vertexID); assert(subpasses.back().size() == 2); // inputs and outputs auto &computePass = get(ComputeTag{}, vertexID, renderGraph); @@ -231,6 +232,7 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn const ccstd::string name = "pass" + std::to_string(passCount++); const auto vertexID = add_vertex(renderGraph, CopyTag{}, name.c_str()); + renderGraph.sortedVertices.emplace_back(vertexID); assert(subpasses.back().size() == 2); // inputs and outputs auto ©Pass = get(CopyTag{}, vertexID, renderGraph); const auto &inputsAndOutputs = subpasses.back(); @@ -260,302 +262,6 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn fgDispatcher.run(); */ } -static void fillBarriers(const ResourceGraph &resourceGraph, const BarrierPair &barrierInfo, framegraph::PassNodeBuilder &builder, PassBarrierPair &barriers) { - auto doFill = [&builder, &resourceGraph](const std::vector &edgeInfo, std::vector &edgeBarriers) { - for (const auto &resBarrier : edgeInfo) { - const auto &name = get(ResourceGraph::NameTag{}, resourceGraph, resBarrier.resourceID); - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resBarrier.resourceID); - auto type = desc.dimension == ResourceDimension::BUFFER ? cc::framegraph::ResourceType::BUFFER : cc::framegraph::ResourceType::TEXTURE; - framegraph::Range layerRange; - framegraph::Range mipRange; - if (type == framegraph::ResourceType::BUFFER) { - auto bufferRange = ccstd::get(resBarrier.beginStatus.range); - layerRange = {0, 0}; - mipRange = {bufferRange.offset, bufferRange.size}; - } else { - auto textureRange = ccstd::get(resBarrier.beginStatus.range); - layerRange = {textureRange.firstSlice, textureRange.numSlices}; - mipRange = {textureRange.mipLevel, textureRange.levelCount}; - } - - edgeBarriers.emplace_back(cc::framegraph::ResourceBarrier{ - type, - resBarrier.type, - builder.readFromBlackboard(framegraph::FrameGraph::stringToHandle(name.c_str())), - {resBarrier.beginStatus.passType, - resBarrier.beginStatus.visibility, - resBarrier.beginStatus.access}, - {resBarrier.endStatus.passType, - resBarrier.endStatus.visibility, - resBarrier.endStatus.access}, - layerRange, - mipRange, - }); - } - }; - - doFill(barrierInfo.frontBarriers, barriers.frontBarriers); - doFill(barrierInfo.rearBarriers, barriers.rearBarriers); -} - -struct TestRenderData { - ccstd::vector> outputTexes; -}; - -struct FrameGraphPassInfo { - framegraph::FrameGraph &frameGraph; - const RenderGraph &renderGraph; - const ResourceGraph &resourceGraph; - const RasterViews &rasterViews; - const ComputeViews &computeViews; - const BarrierMap &barrierMap; - uint32_t passID{0}; - bool isSubpass{false}; - bool subpassEnd{false}; -}; - -static void addPassToFrameGraph(const FrameGraphPassInfo &info) { - const auto &rasterViews = info.rasterViews; - const auto &passID = info.passID; - const auto &barrierMap = info.barrierMap; - const auto &renderGraph = info.renderGraph; - const auto &resourceGraph = info.resourceGraph; - auto &frameGraph = info.frameGraph; - bool isSupass = info.isSubpass; - bool subpassEnd = info.subpassEnd; - - auto forwardSetup = [&](framegraph::PassNodeBuilder &builder, TestRenderData &data) { - if (isSupass) { - builder.subpass(subpassEnd); - } - - auto goThroughRasterViews = [&](const RasterViews &views) { - for (const auto &view : views) { - const auto handle = framegraph::FrameGraph::stringToHandle(view.second.slotName.c_str()); - auto typedHandle = builder.readFromBlackboard(handle); - data.outputTexes.emplace_back(); - auto &lastTex = data.outputTexes.back(); - framegraph::Texture::Descriptor colorTexInfo; - colorTexInfo.format = gfx::Format::RGBA8; - - // if (rasterView.second.accessType == AccessType::READ) { - colorTexInfo.usage = gfx::TextureUsage::INPUT_ATTACHMENT | gfx::TextureUsage::COLOR_ATTACHMENT; - //} - lastTex.first = view.second.accessType; - lastTex.second = static_cast(typedHandle); - - if (framegraph::Handle::IndexType(typedHandle) == framegraph::Handle::UNINITIALIZED) { - colorTexInfo.width = 960; - colorTexInfo.height = 640; - - lastTex.second = builder.create(handle, colorTexInfo); - } - - framegraph::RenderTargetAttachment::Descriptor colorAttachmentInfo; - colorAttachmentInfo.usage = view.second.attachmentType == AttachmentType::RENDER_TARGET ? framegraph::RenderTargetAttachment::Usage::COLOR : framegraph::RenderTargetAttachment::Usage::DEPTH_STENCIL; - colorAttachmentInfo.clearColor = view.second.clearColor; - colorAttachmentInfo.loadOp = view.second.loadOp; - if (view.second.accessType == AccessType::WRITE) { - lastTex.second = builder.write(lastTex.second, colorAttachmentInfo); - builder.writeToBlackboard(handle, lastTex.second); - colorAttachmentInfo.beginAccesses = colorAttachmentInfo.endAccesses = gfx::AccessFlagBit::COLOR_ATTACHMENT_WRITE; - } else { - colorAttachmentInfo.beginAccesses = colorAttachmentInfo.endAccesses = gfx::AccessFlagBit::COLOR_ATTACHMENT_READ; - auto res = builder.read(framegraph::TextureHandle(builder.readFromBlackboard(handle))); - builder.writeToBlackboard(handle, res); - } - } - }; - - auto goThroughComputeViews = [&](const ComputeViews &views) { - for (const auto &pair : views) { - for (const auto &view : pair.second) { - const auto handle = framegraph::FrameGraph::stringToHandle(view.name.c_str()); - auto typedHandle = builder.readFromBlackboard(handle); - data.outputTexes.emplace_back(); - auto &lastTex = data.outputTexes.back(); - framegraph::Texture::Descriptor colorTexInfo; - colorTexInfo.format = gfx::Format::RGBA8; - - // if (rasterView.second.accessType == AccessType::READ) { - colorTexInfo.usage = gfx::TextureUsage::INPUT_ATTACHMENT | gfx::TextureUsage::COLOR_ATTACHMENT; - //} - lastTex.first = view.accessType; - lastTex.second = static_cast(typedHandle); - - if (framegraph::Handle::IndexType(typedHandle) == framegraph::Handle::UNINITIALIZED) { - colorTexInfo.width = 960; - colorTexInfo.height = 640; - - lastTex.second = builder.create(handle, colorTexInfo); - } - - framegraph::RenderTargetAttachment::Descriptor colorAttachmentInfo; - - if (view.accessType == AccessType::WRITE) { - lastTex.second = builder.write(lastTex.second); - builder.writeToBlackboard(handle, lastTex.second); - } else { - auto res = builder.read(framegraph::TextureHandle(builder.readFromBlackboard(handle))); - builder.writeToBlackboard(handle, res); - } - } - } - }; - - goThroughRasterViews(info.rasterViews); - goThroughComputeViews(info.computeViews); - - builder.setViewport({0U, 640U, 0U, 960U, 0.0F, 1.0F}, {0U, 0U, 960U, 640U}); - - if (barrierMap.find(passID + 1) == barrierMap.end()) { - return; - } - const auto &barrier = barrierMap.at(passID + 1); - PassBarrierPair barrierPairs; - fillBarriers(resourceGraph, barrier.blockBarrier, builder, barrierPairs); - builder.setBarrier(barrierPairs); - }; - - auto forwardExec = [](const TestRenderData &data, - const framegraph::DevicePassResourceTable &table) { - /*for(const auto& pair: data.outputTexes) { - if(pair.first == AccessType::WRITE) { - table.getWrite(pair.second); - } - if(pair.first == AccessType::READ) { - table.getRead(pair.second); - } - if(pair.first == AccessType::READ_WRITE) { - table.getRead(pair.second); - table.getWrite(pair.second); - } - }*/ - }; - - auto passHandle = framegraph::FrameGraph::stringToHandle(get(RenderGraph::NameTag{}, renderGraph, passID).c_str()); - - string presentHandle; - - for (const auto &view : rasterViews) { - // write or read_write - if (view.second.accessType != AccessType::READ) { - presentHandle = view.first; - break; - } - } - - frameGraph.addPass(static_cast(ForwardInsertPoint::IP_FORWARD), passHandle, forwardSetup, forwardExec); -} - -static void runTestGraph(const RenderGraph &renderGraph, const ResourceGraph &resourceGraph, const LayoutGraphData &layoutGraphData, const FrameGraphDispatcher &fgDispatcher) { - const auto &barriers = fgDispatcher.getBarriers(); - - framegraph::FrameGraph framegraph; - - auto *device = gfx::Device::getInstance(); - if (!device) { - device = gfx::DeviceManager::create(); - } - - for (const auto passID : makeRange(vertices(renderGraph))) { - visitObject( - passID, renderGraph, - [&](const RasterPass &pass) { - // TestRenderData tmpData; - const auto &subpasses = get(SubpassGraph::SubpassTag{}, pass.subpassGraph); - uint32_t count = 0; - for (const auto &subpass : *subpasses.container) { - FrameGraphPassInfo info = { - framegraph, - renderGraph, - resourceGraph, - subpass.rasterViews, - subpass.computeViews, - fgDispatcher.getBarriers(), - passID, - true, - count < subpasses.container->size() - 1}; - addPassToFrameGraph(info); - ++count; - }; - if ((*subpasses.container).empty()) { - FrameGraphPassInfo info = { - framegraph, - renderGraph, - resourceGraph, - pass.rasterViews, - pass.computeViews, - fgDispatcher.getBarriers(), - passID, - false, - false}; - addPassToFrameGraph(info); - ++count; - } - }, - [&](const ComputePass &pass) { - // TestRenderData tmpData; - FrameGraphPassInfo info = { - framegraph, - renderGraph, - resourceGraph, - {}, - pass.computeViews, - fgDispatcher.getBarriers(), - passID, - false, - false}; - addPassToFrameGraph(info); - }, - [&](const CopyPass &pass) { - auto forwardSetup = [&](framegraph::PassNodeBuilder &builder, TestRenderData &data) { - for (const auto &pair : pass.copyPairs) { - for (size_t i = 0; i < 2; ++i) { - bool write = (i % 2 == 0); - const auto handle = framegraph::FrameGraph::stringToHandle(write ? pair.target.c_str() : pair.source.c_str()); - auto typedHandle = builder.readFromBlackboard(handle); - data.outputTexes.emplace_back(); - auto &lastTex = data.outputTexes.back(); - framegraph::Texture::Descriptor colorTexInfo; - colorTexInfo.format = gfx::Format::RGBA8; - colorTexInfo.usage = write ? gfx::TextureUsage::TRANSFER_DST : gfx::TextureUsage::TRANSFER_SRC; - - lastTex.second = static_cast(typedHandle); - - if (framegraph::Handle::IndexType(typedHandle) == framegraph::Handle::UNINITIALIZED) { - colorTexInfo.width = 960; - colorTexInfo.height = 640; - - lastTex.second = builder.create(handle, colorTexInfo); - } - - if (write) { - lastTex.second = builder.write(lastTex.second); - builder.writeToBlackboard(handle, lastTex.second); - } else { - auto res = builder.read(framegraph::TextureHandle(builder.readFromBlackboard(handle))); - builder.writeToBlackboard(handle, res); - } - } - } - }; - - auto forwardExec = [](const TestRenderData &data, - const framegraph::DevicePassResourceTable &table) { - }; - - auto passHandle = framegraph::FrameGraph::stringToHandle(get(RenderGraph::NameTag{}, renderGraph, passID).c_str()); - framegraph.addPass(static_cast(ForwardInsertPoint::IP_FORWARD), passHandle, forwardSetup, forwardExec); - }, - [&](const RaytracePass &pass) {}, - [&](const auto & /*pass*/) {}); - } - framegraph.compile(); - framegraph.execute(); - framegraph.reset(); -} - #define TEST_CASE_DEFINE \ using namespace cc::render; \ using cc::gfx::AccessFlagBit; \ diff --git a/native/tests/unit-test/src/complicated_barrier_case.cpp b/native/tests/unit-test/src/complicated_barrier_case.cpp index 3fdb5ae8a40..a837a4867a1 100644 --- a/native/tests/unit-test/src/complicated_barrier_case.cpp +++ b/native/tests/unit-test/src/complicated_barrier_case.cpp @@ -46,202 +46,67 @@ TEST(complicatedBarrierTest, test12) { }); }; - const auto& barrierMap = fgDispatcher.getBarriers(); + const auto& barrierMap = fgDispatcher.resourceAccessGraph.barrier; const auto& rag = fgDispatcher.resourceAccessGraph; - ExpectEq(rag._vertices.size() == 17, true); + ExpectEq(rag._vertices.size() == 23, true); // head const auto& head = barrierMap.at(0); - ExpectEq(head.blockBarrier.frontBarriers.empty(), true); - ExpectEq(head.blockBarrier.rearBarriers.empty(), true); - ExpectEq(head.subpassBarriers.empty(), true); + ExpectEq(head.frontBarriers.empty(), true); + ExpectEq(head.rearBarriers.empty(), true); // 1st node const auto& node1 = barrierMap.at(1); // block barrier: replace by rnderpass info, same below //ExpectEq(node1.blockBarrier.frontBarriers.size() == 2, true); //ExpectEq(node1.blockBarrier.rearBarriers.size() == 1, true); - ExpectEq(node1.subpassBarriers.empty(), false); - - //ExpectEq(node1.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].resourceID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].beginStatus.vertID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].endStatus.vertID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].endStatus.access == MemoryAccessBit::READ_ONLY, true); - - //subpass barrier: like normal pass - const auto& node1subpass = node1.subpassBarriers; - ExpectEq(node1subpass[0].frontBarriers.empty(), false); - ExpectEq(node1subpass[0].rearBarriers.size() == 1, true); - - // undefined external depends - const auto& node1subpassres0 = node1subpass[0].rearBarriers[0]; - ExpectEq(node1subpassres0.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node1subpassres0.resourceID == 0, true); - // vertid in subpass:subpass index, same below - ExpectEq(node1subpassres0.beginStatus.vertID == 0, true); - ExpectEq(node1subpassres0.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node1subpassres0.beginStatus.passType == PassType::RASTER, true); - ExpectEq(node1subpassres0.endStatus.vertID == 1, true); - ; - ExpectEq(node1subpassres0.endStatus.access == MemoryAccessBit::READ_ONLY, true); - ExpectEq(node1subpassres0.endStatus.passType == PassType::RASTER, true); - - ExpectEq(node1subpass[1].frontBarriers.size() == 1, true); - const auto& node1subpassres1 = node1subpass[1].rearBarriers[0]; - ExpectEq(node1subpassres1.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node1subpassres1.resourceID == 1, true); - ExpectEq(node1subpassres1.beginStatus.vertID == 1, true); - ExpectEq(node1subpassres1.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node1subpassres1.beginStatus.passType == PassType::RASTER, true); - ExpectEq(node1subpassres1.endStatus.vertID == 1, true); - ; - ExpectEq(node1subpassres1.endStatus.access == MemoryAccessBit::READ_ONLY, true); - ExpectEq(node1subpassres1.endStatus.passType == PassType::RASTER, true); - - //node2 - const auto& node2 = barrierMap.at(2); - //ExpectEq(node2.blockBarrier.frontBarriers.size() == 2, true); - //ExpectEq(node2.blockBarrier.rearBarriers.size() == 1, true); - ExpectEq(node2.subpassBarriers.size() == 2, true); - - //const auto& node2blockRear = node2.blockBarrier.rearBarriers; - //auto iter3in2 = findBarrierByResID(node2blockRear, 3); - //const auto& res3in2 = (*iter3in2); - //ExpectEq(res3in2.resourceID == 3, true); - //ExpectEq(res3in2.type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(res3in2.beginStatus.vertID == 2, true); - //ExpectEq(res3in2.beginStatus.passType == PassType::RASTER, true); - //ExpectEq(res3in2.endStatus.vertID == 2, true); - //ExpectEq(res3in2.endStatus.passType == PassType::RASTER, true); - - const auto& node2subpass = node2.subpassBarriers; - ExpectEq(node2subpass.empty(), false); - // subpass dependency instead of extra barrier - ExpectEq(node2subpass[0].frontBarriers.size() == 1, true); - ExpectEq(node2subpass[0].rearBarriers.empty(), false); - - const auto& node2subpassRes2 = node2subpass[0].rearBarriers[0]; - ExpectEq(node2subpassRes2.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node2subpassRes2.resourceID == 2, true); - ExpectEq(node2subpassRes2.beginStatus.vertID == 0, true); - ExpectEq(node2subpassRes2.beginStatus.passType == PassType::RASTER, true); - ExpectEq(node2subpassRes2.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node2subpassRes2.endStatus.vertID == 1, true); - ExpectEq(node2subpassRes2.endStatus.access == MemoryAccessBit::READ_ONLY, true); //node3 // renderpass info layout instead - const auto& node3 = barrierMap.at(3); - ExpectEq(node3.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node3.blockBarrier.rearBarriers.empty(), true); - - // subpass barrier size is the same as renderpass subpassinfo, though maybe empty. - ExpectEq(node3.subpassBarriers.size() == 1, true); - ExpectEq(node3.subpassBarriers.front().frontBarriers.empty(), true); - ExpectEq(node3.subpassBarriers.front().rearBarriers.empty(), true); - - //node4 - const auto& node4 = barrierMap.at(4); - //ExpectEq(node4.blockBarrier.frontBarriers.size() == 2, true); - //ExpectEq(node4.blockBarrier.rearBarriers.size() == 1, true); - ExpectEq(node4.subpassBarriers.empty(), false); - - //const auto& node4block = node4.blockBarrier; - //auto iter5in4 = findBarrierByResID(node4block.rearBarriers, 5); - //ExpectEq(iter5in4 == node4block.rearBarriers.end(), true); - - //auto iter6in4 = findBarrierByResID(node4block.rearBarriers, 6); - //ExpectEq(iter6in4 != node4block.rearBarriers.end(), true); - //ExpectEq((*iter6in4).type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq((*iter6in4).resourceID == 6, true); - //ExpectEq((*iter6in4).beginStatus.vertID == 4, true); - //ExpectEq((*iter6in4).endStatus.vertID == 14, true); - - const auto& node4subpass0 = node4.subpassBarriers[0]; - // subpass undefined external depends - ExpectEq(node4subpass0.frontBarriers.empty(), false); - ExpectEq(node4subpass0.rearBarriers.size() == 1, true); - ExpectEq(node4subpass0.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node4subpass0.rearBarriers[0].resourceID == 5, true); - ExpectEq(node4subpass0.rearBarriers[0].beginStatus.vertID == 0, true); - ExpectEq(node4subpass0.rearBarriers[0].beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node4subpass0.rearBarriers[0].endStatus.vertID == 1, true); - ExpectEq(node4subpass0.rearBarriers[0].endStatus.access == MemoryAccessBit::READ_ONLY, true); - - const auto& node4subpass1 = node4.subpassBarriers[1]; - ExpectEq(node4subpass1.frontBarriers.empty(), false); - ExpectEq(node4subpass1.rearBarriers.size() == 1, true); - ExpectEq(node4subpass1.rearBarriers[0].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - ExpectEq(node4subpass1.rearBarriers[0].resourceID == 6, true); - // external subpass depends - ExpectEq(node4subpass1.rearBarriers[0].beginStatus.vertID == 0xFFFFFFFF, true); - ExpectEq(node4subpass1.rearBarriers[0].beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - // external subpass depends - ExpectEq(node4subpass1.rearBarriers[0].endStatus.vertID == 0xFFFFFFFF, true); - ExpectEq(node4subpass1.rearBarriers[0].endStatus.access == MemoryAccessBit::READ_ONLY, true); - - const auto& node5 = barrierMap.at(5); - ExpectEq(node5.blockBarrier.frontBarriers.size() == 1, true); - ExpectEq(node5.blockBarrier.rearBarriers.size() == 1, true); - // not raster pass - ExpectEq(node5.subpassBarriers.empty(), true); - - auto iter7in5 = findBarrierByResID(node5.blockBarrier.rearBarriers, 7); - const auto& res7in5 = (*iter7in5); - ExpectEq(res7in5.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(res7in5.resourceID == 7, true); - ExpectEq(res7in5.beginStatus.vertID == 5, true); - ExpectEq(res7in5.endStatus.vertID == 5, true); - ExpectEq(res7in5.beginStatus.passType == PassType::COPY, true); - ExpectEq(res7in5.endStatus.passType == PassType::COPY, true); - ExpectEq(res7in5.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(res7in5.endStatus.access == MemoryAccessBit::READ_ONLY, true); - - const auto& node6 = barrierMap.at(6); - ExpectEq(node6.blockBarrier.frontBarriers.size() == 1, true); + const auto& node3 = barrierMap.at(7); + ExpectEq(node3.frontBarriers.empty(), true); + ExpectEq(node3.rearBarriers.empty(), true); + + const auto& node11 = barrierMap.at(11); + ExpectEq(node11.frontBarriers.size() == 1, true); + ExpectEq(node11.rearBarriers.size() == 1, true); + + auto iter7in11 = findBarrierByResID(node11.rearBarriers, 7); + const auto& res7in11 = (*iter7in11); + ExpectEq(res7in11.type == cc::gfx::BarrierType::FULL, true); + ExpectEq(res7in11.resourceID == 7, true); + ExpectEq(res7in11.beginStatus.accessFlag == AccessFlagBit::TRANSFER_WRITE, true); + ExpectEq(res7in11.endStatus.accessFlag == AccessFlagBit::TRANSFER_READ, true); + + const auto& node12 = barrierMap.at(12); + ExpectEq(node12.frontBarriers.size() == 1, true); // resource later used by raster pass, so that layout can be transferred automatically. - ExpectEq(node6.blockBarrier.rearBarriers.empty(), true); - // not a raster pass - ExpectEq(node6.subpassBarriers.empty(), true); + ExpectEq(node12.rearBarriers.empty(), true); // node7 - const auto& node7 = barrierMap.at(7); + const auto& node13 = barrierMap.at(13); // undefined layout already in initial layout - ExpectEq(node7.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node7.blockBarrier.rearBarriers.empty(), true); - ExpectEq(node7.subpassBarriers.empty(), false); - - ExpectEq(node7.blockBarrier.rearBarriers.size(), 0); - - //node8: almost the same as node7 - //node9: almost the same as node8 - //node10: ditto - //node11: ditto - //node12: ditto + ExpectEq(node13.frontBarriers.empty(), true); + ExpectEq(node13.rearBarriers.empty(), true); //node13 - const auto& node13 = barrierMap.at(13); - ExpectEq(node13.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node13.blockBarrier.rearBarriers.size(), 0); - ExpectEq(node13.subpassBarriers.empty(), false); + const auto& node19 = barrierMap.at(19); + ExpectEq(node19.frontBarriers.size(), 0); + ExpectEq(node19.rearBarriers.size(), 0); //node14: almost the same as 13 //node15: ditto - const auto& node15 = barrierMap.at(15); - const auto& theone = node15.blockBarrier.rearBarriers.front(); + const auto& node21 = barrierMap.at(21); + const auto& theone = node21.rearBarriers.front(); ExpectEq(theone.resourceID == 22, true); ExpectEq(theone.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(theone.endStatus.vertID == 0xFFFFFFFF, true); + ExpectEq(theone.endStatus.accessFlag == AccessFlagBit::PRESENT, true); //node16 const auto& node16 = barrierMap.at(16); - ExpectEq(node16.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node16.blockBarrier.rearBarriers.empty(), true); - // not raster pass - ExpectEq(node16.subpassBarriers.empty(), true); + ExpectEq(node16.frontBarriers.empty(), true); + ExpectEq(node16.rearBarriers.empty(), true); //runTestGraph(renderGraph, rescGraph, layoutGraphData, fgDispatcher); } diff --git a/native/tests/unit-test/src/simple_barrier_test.cpp b/native/tests/unit-test/src/simple_barrier_test.cpp index d6c7dc7b5fc..108418e7ced 100644 --- a/native/tests/unit-test/src/simple_barrier_test.cpp +++ b/native/tests/unit-test/src/simple_barrier_test.cpp @@ -40,44 +40,22 @@ TEST(barrierTest, test10) { FrameGraphDispatcher fgDispatcher(rescGraph, renderGraph, layoutGraphData, resource, resource); fgDispatcher.run(); - const auto& barrierMap = fgDispatcher.getBarriers(); + const auto& barrierMap = fgDispatcher.resourceAccessGraph.barrier; const auto& rag = fgDispatcher.resourceAccessGraph; - ExpectEq(rag._vertices.size() == 4, true); + ExpectEq(rag._vertices.size() == 6, true); // head const auto& head = barrierMap.at(0); - ExpectEq(head.blockBarrier.frontBarriers.empty(), true); - ExpectEq(head.blockBarrier.rearBarriers.empty(), true); - - // 1st node - const auto& node1 = barrierMap.at(1); - //ExpectEq(node1.blockBarrier.frontBarriers.size() == 4, true); - //ExpectEq(node1.blockBarrier.rearBarriers.size() == 1, true); - - // undefined external - ExpectEq(node1.subpassBarriers[0].frontBarriers.size() == 3, true); - ExpectEq(node1.subpassBarriers[0].rearBarriers.size() == 3, true); - - // undefined external - ExpectEq(node1.subpassBarriers[1].frontBarriers.size() == 1, true); - ExpectEq(node1.subpassBarriers[1].rearBarriers.size() == 1, true); - - //const auto& barrier = node1.blockBarrier.rearBarriers[0]; - //ExpectEq(barrier.type == BarrierType::FULL, true); - //ExpectEq(barrier.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ////resID 3 - //ExpectEq(barrier.beginStatus.visibility == std::get<2>(layoutInfo[0][3]), true); + ExpectEq(head.frontBarriers.empty(), true); + ExpectEq(head.rearBarriers.empty(), true); //// 2nd node - const auto& node2 = barrierMap.at(2); - ExpectEq(node2.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node2.blockBarrier.rearBarriers.size() == 1, true); + const auto& node4 = barrierMap.at(4); + ExpectEq(node4.frontBarriers.size(), 0); + ExpectEq(node4.rearBarriers.size() == 1, true); - const auto& node2RearBarrier0 = node2.blockBarrier.rearBarriers.back(); - ExpectEq(node2RearBarrier0.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node2RearBarrier0.beginStatus.visibility == ShaderStageFlagBit::FRAGMENT, true); - ExpectEq(node2RearBarrier0.endStatus.accessFlag == AccessFlagBit::PRESENT, true); - //endstatus: whatever it was, it's COLOR_ATTACHMENT_OPTIMAL + const auto& node4RearBarrier0 = node4.rearBarriers.back(); + ExpectEq(node4RearBarrier0.endStatus.accessFlag == AccessFlagBit::PRESENT, true); //runTestGraph(renderGraph, rescGraph, layoutGraphData, fgDispatcher); } diff --git a/native/tests/unit-test/src/simple_closed_barrier_test.cpp b/native/tests/unit-test/src/simple_closed_barrier_test.cpp index 644132e90fb..095cc345508 100644 --- a/native/tests/unit-test/src/simple_closed_barrier_test.cpp +++ b/native/tests/unit-test/src/simple_closed_barrier_test.cpp @@ -40,148 +40,29 @@ TEST(simpleClosedBarrierTest, test11) { FrameGraphDispatcher fgDispatcher(rescGraph, renderGraph, layoutGraphData, resource, resource); fgDispatcher.run(); - const auto& barrierMap = fgDispatcher.getBarriers(); + const auto& barrierMap = fgDispatcher.resourceAccessGraph.barrier; const auto& rag = fgDispatcher.resourceAccessGraph; ExpectEq(rag._vertices.size() == 10, true); // head const auto& head = barrierMap.at(0); - ExpectEq(head.blockBarrier.frontBarriers.empty(), true); - ExpectEq(head.blockBarrier.rearBarriers.empty(), true); - ExpectEq(head.subpassBarriers.empty(), true); + ExpectEq(head.frontBarriers.empty(), true); + ExpectEq(head.rearBarriers.empty(), true); // 1st node const auto& node1 = barrierMap.at(1); - ExpectEq(node1.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node1.blockBarrier.rearBarriers.size(), 0); - ExpectEq(node1.subpassBarriers.size() == 1, true); - ExpectEq(node1.subpassBarriers.front().frontBarriers.empty(), true); - ExpectEq(node1.subpassBarriers.front().rearBarriers.empty(), true); - - // transitioned by renderpass info - //ExpectEq(node1.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].endStatus.vertID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[1].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node1.blockBarrier.rearBarriers[1].endStatus.vertID == 3, true); + ExpectEq(node1.frontBarriers.size(), 0); + ExpectEq(node1.rearBarriers.size(), 0); const auto& node2 = barrierMap.at(2); - ExpectEq(node2.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node2.blockBarrier.rearBarriers.size(), 0); - ExpectEq(node2.subpassBarriers.size() == 1, true); - ExpectEq(node2.subpassBarriers.front().frontBarriers.empty(), true); - ExpectEq(node2.subpassBarriers.front().rearBarriers.empty(), true); - - // ditto - //// res3 - //ExpectEq(node2.blockBarrier.rearBarriers[1].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node2.blockBarrier.rearBarriers[1].beginStatus.vertID == 2, true); - //ExpectEq(node2.blockBarrier.rearBarriers[1].endStatus.vertID == 5, true); - //// res2 - //ExpectEq(node2.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node2.blockBarrier.rearBarriers[0].beginStatus.vertID == 2, true); - //ExpectEq(node2.blockBarrier.rearBarriers[0].endStatus.vertID == 4, true); - - //const auto& node3 = barrierMap.at(3); - //ExpectEq(node3.blockBarrier.frontBarriers.size() == 3, true); - //ExpectEq(node3.blockBarrier.rearBarriers.size() == 2, true); - //ExpectEq(node3.subpassBarriers.empty(), true); - - //const auto& res1Index = std::find_if(node3.blockBarrier.frontBarriers.begin(), node3.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 1; }); - //ExpectEq(res1Index != node3.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res1Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res1Index->beginStatus.vertID == 1, true); - //ExpectEq(res1Index->endStatus.vertID == 3, true); - //// res 5 - //ExpectEq(node3.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node3.blockBarrier.rearBarriers[0].beginStatus.vertID == 3, true); - //ExpectEq(node3.blockBarrier.rearBarriers[0].endStatus.vertID == 3, true); - //// res 4 - //ExpectEq(node3.blockBarrier.rearBarriers[1].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node3.blockBarrier.rearBarriers[1].beginStatus.vertID == 3, true); - //ExpectEq(node3.blockBarrier.rearBarriers[1].endStatus.vertID == 5, true); - - //const auto& node4 = barrierMap.at(4); - //ExpectEq(node4.blockBarrier.frontBarriers.size() == 2, true); - //ExpectEq(node4.blockBarrier.rearBarriers.size() == 1, true); - //ExpectEq(node4.subpassBarriers.empty(), true); - - //const auto& res3Index = std::find_if(node4.blockBarrier.frontBarriers.begin(), node4.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 3; }); - //ExpectEq(res3Index != node4.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res3Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res3Index->beginStatus.vertID == 2, true); - //ExpectEq(res3Index->endStatus.vertID == 4, true); - - //ExpectEq(node4.blockBarrier.rearBarriers[0].resourceID == 6, true); - //ExpectEq(node4.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node4.blockBarrier.rearBarriers[0].beginStatus.vertID == 4, true); - //ExpectEq(node4.blockBarrier.rearBarriers[0].endStatus.vertID == 4, true); - - //const auto& node5 = barrierMap.at(5); - //ExpectEq(node5.blockBarrier.frontBarriers.size() == 3, true); - //ExpectEq(node5.blockBarrier.rearBarriers.size() == 1, true); - //ExpectEq(node5.subpassBarriers.empty(), true); - - //const auto& res2Index = std::find_if(node5.blockBarrier.frontBarriers.begin(), node5.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 2; }); - //ExpectEq(res2Index != node5.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res2Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res2Index->beginStatus.vertID == 2, true); - //ExpectEq(res2Index->endStatus.vertID == 5, true); - //const auto& res4Index = std::find_if(node5.blockBarrier.frontBarriers.begin(), node5.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 4; }); - //ExpectEq(res4Index != node5.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res4Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res4Index->beginStatus.vertID == 3, true); - //ExpectEq(res4Index->endStatus.vertID == 5, true); - - //ExpectEq(node5.blockBarrier.rearBarriers[0].resourceID == 7, true); - //ExpectEq(node5.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node5.blockBarrier.rearBarriers[0].beginStatus.vertID == 5, true); - //ExpectEq(node5.blockBarrier.rearBarriers[0].endStatus.vertID == 8, true); - - //const auto& node6 = barrierMap.at(6); - //ExpectEq(node6.blockBarrier.frontBarriers.size() == 1, true); - //ExpectEq(node6.blockBarrier.rearBarriers.size() == 1, true); - //ExpectEq(node6.subpassBarriers.empty(), true); - - //ExpectEq(node6.blockBarrier.rearBarriers[0].resourceID == 8, true); - //ExpectEq(node6.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node6.blockBarrier.rearBarriers[0].beginStatus.vertID == 6, true); - //ExpectEq(node6.blockBarrier.rearBarriers[0].endStatus.vertID == 6, true); - - //const auto& node7 = barrierMap.at(7); - //ExpectEq(node7.subpassBarriers.empty(), true); - //ExpectEq(node7.blockBarrier.frontBarriers.size() == 1, true); - //ExpectEq(node7.blockBarrier.rearBarriers.size() == 1, true); - - //ExpectEq(node7.blockBarrier.rearBarriers[0].resourceID == 9, true); - //ExpectEq(node7.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node7.blockBarrier.rearBarriers[0].beginStatus.vertID == 7, true); - //ExpectEq(node7.blockBarrier.rearBarriers[0].endStatus.vertID == 7, true); - - //const auto& node8 = barrierMap.at(8); - //ExpectEq(node8.subpassBarriers.empty(), true); - //ExpectEq(node8.blockBarrier.frontBarriers.empty(), false); // size == 1 - //ExpectEq(node8.blockBarrier.rearBarriers.size() == 1, true); - - //ExpectEq(node8.blockBarrier.frontBarriers[1].resourceID == 7, true); - //ExpectEq(node8.blockBarrier.frontBarriers[1].type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(node8.blockBarrier.frontBarriers[1].beginStatus.vertID == 5, true); - //ExpectEq(node8.blockBarrier.frontBarriers[1].endStatus.vertID == 8, true); - - //ExpectEq(node8.blockBarrier.rearBarriers[0].resourceID == 22, true); - //ExpectEq(node8.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node8.blockBarrier.rearBarriers[0].beginStatus.vertID == 8, true); - //ExpectEq(node8.blockBarrier.rearBarriers[0].endStatus.vertID == 0xFFFFFFFF, true); + ExpectEq(node2.frontBarriers.size(), 0); + ExpectEq(node2.rearBarriers.size(), 0); // TODO: validate renderpassInfo instead const auto& node9 = barrierMap.at(9); - ExpectEq(node9.subpassBarriers.empty(), true); - ExpectEq(node9.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node9.blockBarrier.rearBarriers.empty(), true); - // const auto& node2RearBarrier0 = node2.blockBarrier.rearBarriers.back(); - // ExpectEq(node2RearBarrier0.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - // ExpectEq(node2RearBarrier0.beginStatus.visibility == ShaderStageFlagBit::VERTEX, true); - // ExpectEq(node2RearBarrier0.endStatus.access == MemoryAccessBit::READ_ONLY, true); + ExpectEq(node9.frontBarriers.empty(), true); + ExpectEq(node9.rearBarriers.empty(), true); //endstatus: whatever it was, it's COLOR_ATTACHMENT_OPTIMAL //runTestGraph(renderGraph, rescGraph, layoutGraphData, fgDispatcher); From 095b08334f5469c68b53c716a6fbf696fa222bf1 Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Mon, 31 Jul 2023 18:19:31 +0800 Subject: [PATCH 02/82] loading subresource as needed & all metal shader delayed compile (#155) * name fix * remove ds input test code in metal * compute view subresname collect * subres full name now * clang-tidy --------- Co-authored-by: Zeqiang Li --- native/cocos/renderer/gfx-metal/MTLShader.mm | 6 +- native/cocos/renderer/gfx-metal/MTLUtils.mm | 58 +--------------- .../pipeline/custom/FrameGraphDispatcher.cpp | 67 ++++++++++++++++--- .../pipeline/custom/NativeExecutor.cpp | 15 +++-- 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/native/cocos/renderer/gfx-metal/MTLShader.mm b/native/cocos/renderer/gfx-metal/MTLShader.mm index 482eb4d61af..24b7e35b6a4 100644 --- a/native/cocos/renderer/gfx-metal/MTLShader.mm +++ b/native/cocos/renderer/gfx-metal/MTLShader.mm @@ -73,9 +73,9 @@ of this software and associated engine source code (the "Software"), a limited, _specializedFragFuncs = [[NSMutableDictionary alloc] init]; // spirv-cross for input attachment needs RenderPass to build [[color(index)]], // build gpu shader only when there is no subPass input. - if (!checkInputAttachment(info)) { - gpuShader(nullptr, 0); - } +// if (!checkInputAttachment(info)) { +// gpuShader(nullptr, 0); +// } } void CCMTLShader::doDestroy() { diff --git a/native/cocos/renderer/gfx-metal/MTLUtils.mm b/native/cocos/renderer/gfx-metal/MTLUtils.mm index f78f8535877..cf4f3fc7a8c 100644 --- a/native/cocos/renderer/gfx-metal/MTLUtils.mm +++ b/native/cocos/renderer/gfx-metal/MTLUtils.mm @@ -41,8 +41,6 @@ of this software and associated engine source code (the "Software"), a limited, namespace gfx { namespace { -static constexpr bool ENABLE_DS_INPUT = false; - ccstd::unordered_map pipelineMap; ccstd::unordered_map renderPassMap; @@ -1059,11 +1057,6 @@ void main() { } } - struct AttachmentDesc{ - uint32_t slot{0}; - std::string name; - }; - AttachmentDesc depthInput, stencilInput; if (executionModel == spv::ExecutionModelFragment) { auto* ccRenderPass = static_cast(renderPass); const auto& readBuffer = ccRenderPass ? ccRenderPass->getReadBuffer(subpassIndex) : ccstd::vector{}; @@ -1073,18 +1066,8 @@ void main() { const auto &attachment = resources.subpass_inputs[i]; auto inputIndex = msl.get_decoration(attachment.id, spv::DecorationInputAttachmentIndex); auto loc = inputIndex >= readBuffer.size() ? inputIndex : readBuffer[inputIndex]; - if(renderPass) { - if(loc == renderPass->getColorAttachments().size()) { - depthInput.slot = inputIndex; - depthInput.name = attachment.name; - continue; - } - if(loc == (renderPass->getColorAttachments().size() + 1)) { - stencilInput.slot = inputIndex; - stencilInput.name = attachment.name; - continue;; - } - } + // depth stencil input not support in metal + CC_ASSERT(loc != renderPass->getColorAttachments().size()); auto& input = gpuShader->inputs.emplace_back(); input.name = attachment.name; msl.set_decoration(attachment.id, spv::DecorationInputAttachmentIndex, loc); @@ -1120,43 +1103,6 @@ void main() { CC_LOG_ERROR("Compile to MSL failed."); CC_LOG_ERROR("%s", output.c_str()); } - if constexpr(ENABLE_DS_INPUT) { - if(!depthInput.name.empty() || !stencilInput.name.empty()) { - auto outIndex = output.find("struct main0_out"); - std::string depthDecl = depthInput.name.empty() ? "" : "\n float depth [[depth(less)]];"; - std::string stencilDecl = stencilInput.name.empty() ? "" : "\n uint stencil [[stencil]];"; - auto dsDecl = "struct DSInput\n{" + depthDecl + stencilDecl + " \n};\n"; - output.insert(outIndex, dsDecl); - bool hasDepth{false}; - if (!depthInput.name.empty()) { - std::string depthName(depthInput.name.substr(1)); - std::string depthInExp = "[, ]*float4 " + depthName + "([^\\)]+\\))\\]\\]"; - std::regex depthInputExp(depthInExp); - output = std::regex_replace(output, depthInputExp, ""); - std::string_view immutableOut{"fragment main0_out"}; - auto entryIndex = output.find(immutableOut); - auto bodyIndex = output.find_first_of("{", entryIndex + 1); - output = output.insert(bodyIndex + 1, - "\nDSInput __dsInput{};\nfloat " + depthName + " = __dsInput.depth;"); - hasDepth = true; - } - if(!stencilInput.name.empty()) { - std::string stencilName(stencilInput.name.substr(1)); - std::string stencilInExp = "[, ]*int4 " + stencilName + "([^\\)]+\\))\\]\\]"; - std::regex stencilInputExp(stencilInExp); - output = std::regex_replace(output, stencilInputExp, ""); - std::string_view immutableOut{"fragment main0_out"}; - auto entryIndex = output.find(immutableOut); - auto bodyIndex = output.find_first_of("{", entryIndex + 1); - std::string declStr = hasDepth ? "" : "\nDSInput __dsInput{};"; - output = output.insert(bodyIndex + 1, - declStr + "\nuint " + stencilName + " = __dsInput.stencil;"); - std::regex usingValExp(stencilName + "\\.[rx]"); - output = std::regex_replace(output, usingValExp, stencilName); - } - - } - } return output; } diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index af02a891d01..6cdd864a2b4 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -169,7 +169,7 @@ PmrFlatMap FrameGraphDispatcher:: if (!rasterViews.empty()) { NameLocalID unused{128}; // input sort by slot name - ccstd::pmr::map> inputs(scratch); + ccstd::pmr::map> inputs(scratch); for (const auto &[resourceName, rasterView] : rasterViews) { if (rasterView.accessType != AccessType::WRITE) { if (!defaultAttachment(rasterView.slotName)) { @@ -189,8 +189,10 @@ PmrFlatMap FrameGraphDispatcher:: } // build pass resources for (const auto &[slotName, nameInfo] : inputs) { - auto resID = realResourceID(nameInfo.first); - resID = locateSubres(resID, resourceGraph, nameInfo.second); + auto resID = realResourceID(nameInfo.first.data()); + if (!nameInfo.second.empty()) { + resID = locateSubres(resID, resourceGraph, nameInfo.second); + } resourceIndex.emplace(unused, resID); unused.value++; } @@ -543,7 +545,7 @@ auto dependencyCheck(ResourceAccessGraph &rag, ResourceAccessGraph::vertex_descr if (rag.leafPasses.find(lastVertID) != rag.leafPasses.end()) { rag.leafPasses.erase(lastVertID); } - + if(viewStatus.access != AccessType::WRITE) { subResourceFeedback(resourceGraph, resourceID, desc.format); } @@ -811,33 +813,68 @@ void fillRenderPassInfo(const AttachmentMap &colorMap, } }; +[[nodiscard("concat")]] ccstd::pmr::string concatResName( + std::string_view name0, + std::string_view name1, + boost::container::pmr::memory_resource *scratch) { + ccstd::pmr::string name(name0, scratch); + name += "/"; + name += name1; + return name; +} + void extractNames(const ccstd::pmr::string &resName, const RasterView &view, ccstd::pmr::vector> &names) { // depth_stencil if (view.attachmentType == AttachmentType::DEPTH_STENCIL) { if (!defaultAttachment(view.slotName)) { - if (strstr(resName.c_str(), "/depth")) { + if (strstr(resName.c_str(), "/")) { names.emplace_back(resName, 0); } else { - names.emplace_back(resName + "/depth", 0); + auto &subresName = names.emplace_back(); + subresName.first = concatResName(resName, DEPTH_PLANE_NAME, names.get_allocator().resource()); + subresName.second = 0; } } if (!defaultAttachment(view.slotName1)) { - if (strstr(resName.c_str(), "/stencil")) { + if (strstr(resName.c_str(), "/")) { names.emplace_back(resName, 1); } else { - names.emplace_back(resName + "/stencil", 1); + auto &subresName = names.emplace_back(); + subresName.first = concatResName(resName, STENCIL_PLANE_NAME, names.get_allocator().resource()); + subresName.second = 1; } } } + // cube + + // array + if (names.empty()) { names.emplace_back(resName, 0); } +} + +[[nodiscard("subresName")]] ccstd::pmr::string getSubresName(const ccstd::pmr::string &resName, + uint32_t planeID, const ResourceGraph& resg, + boost::container::pmr::memory_resource* scratch) { + const auto& desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); + if(desc.format == gfx::Format::DEPTH_STENCIL) { + auto nameView = planeID == 0 ? DEPTH_PLANE_NAME : STENCIL_PLANE_NAME; + const auto &subresName = concatResName(resName, nameView, scratch); + return subresName; + } + + // cube // array + + // UNREACHABLE + CC_ASSERT(false); + return ""; } auto checkRasterViews(const Graphs &graphs, @@ -858,7 +895,6 @@ auto checkRasterViews(const Graphs &graphs, for (const auto &pair : rasterViews) { const auto &rasterView = pair.second; const auto &resName = pair.first; - ccstd::pmr::vector> names(resourceAccessGraph.get_allocator()); const auto resID = vertex(resName, resourceGraph); auto access = rasterView.accessType; gfx::ShaderStageFlagBit originVis = getVisibility(renderGraph, layoutGraphData, passID, pair.second.slotName) | explicitVis | pair.second.shaderStageFlags; @@ -884,6 +920,12 @@ auto checkRasterViews(const Graphs &graphs, rasterView.storeOp, rasterView.attachmentType}); hasDS |= rasterView.attachmentType == AttachmentType::DEPTH_STENCIL; + + ccstd::pmr::vector> names(resourceAccessGraph.get_allocator()); + extractNames(resName, rasterView, names); + for (const auto& [subresFullName, plane] : names) { + resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); + } } return std::make_tuple(dependent, hasDS); } @@ -922,6 +964,11 @@ bool checkComputeViews(const Graphs &graphs, ResourceAccessGraph::vertex_descrip tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); tryAddEdge(lastVertId, ragVertID, relationGraph); dependent = lastVertId != EXPECT_START_ID; + + if(out_degree(resID, resourceGraph)) { + const auto& subresFullName = getSubresName(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); + resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); + } } } @@ -1414,7 +1461,7 @@ bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const Resour void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) { const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - + if(moveValidation(pass, resourceAccessGraph, resourceGraph)) { for(const auto& pair : pass.movePairs) { auto srcResourceRange = getResourceRange(vertex(pair.source, resourceGraph), resourceGraph); diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 7e631e10b57..5bba3ec861c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -1570,10 +1570,17 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { void end(const gfx::Viewport& pass, RenderGraph::vertex_descriptor vertID) const { } - void mountResource(const ccstd::pmr::string& name) const { - auto resID = ctx.fgd.resourceAccessGraph.resourceIndex.at(name); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - ctx.resourceGraph.mount(ctx.device, resID); + void mountResource(const ccstd::pmr::string& name) const { // NOLINT(misc-no-recursion) + auto resIter = ctx.fgd.resourceAccessGraph.resourceIndex.find(name); + if (resIter != ctx.fgd.resourceAccessGraph.resourceIndex.end()) { + auto resID = resIter->second; + auto& resg = ctx.resourceGraph; + resg.mount(ctx.device, resID); + for (const auto& subres : makeRange(children(resID, resg))) { + const auto& subresName = get(ResourceGraph::NameTag{}, resg, subres.target); + mountResource(subresName); + } + } } void mountResources(const Subpass& pass) const { From 00f5a5a34acabac6ac88d859915fb82d6e8bc304 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Wed, 2 Aug 2023 15:55:17 +0800 Subject: [PATCH 03/82] Complete Scene Culling (#156) --- cocos/core/geometry/intersect.ts | 54 ++- cocos/render-scene/scene/camera.ts | 39 +- cocos/rendering/custom/compiler.ts | 118 +++-- cocos/rendering/custom/define.ts | 65 ++- cocos/rendering/custom/executor.ts | 275 ++---------- cocos/rendering/custom/scene-culling.ts | 420 ++++++++++++++++++ cocos/rendering/custom/web-pipeline-types.ts | 234 ++++++++++ cocos/rendering/custom/web-pipeline.ts | 36 +- .../post-process/passes/forward-pass.ts | 20 +- .../post-process/passes/skin-pass.ts | 52 ++- .../pipeline/custom/NativeSceneCulling.cpp | 36 +- 11 files changed, 974 insertions(+), 375 deletions(-) create mode 100644 cocos/rendering/custom/scene-culling.ts create mode 100644 cocos/rendering/custom/web-pipeline-types.ts diff --git a/cocos/core/geometry/intersect.ts b/cocos/core/geometry/intersect.ts index 157b6578dfa..fff0a2702dc 100644 --- a/cocos/core/geometry/intersect.ts +++ b/cocos/core/geometry/intersect.ts @@ -413,10 +413,12 @@ const lineTriangle = (function (): (line: Line, triangle: Triangle, outPt?: Vec3 const u = 1.0 - v - w; // outPt = u*a + v*d + w*c; - Vec3.set(outPt, + Vec3.set( + outPt, triangle.a.x * u + triangle.b.x * v + triangle.c.x * w, triangle.a.y * u + triangle.b.y * v + triangle.c.y * w, - triangle.a.z * u + triangle.b.z * v + triangle.c.z * w); + triangle.a.z * u + triangle.b.z * v + triangle.c.z * w, + ); } return 1; @@ -527,38 +529,54 @@ function getAABBVertices (min: Vec3, max: Vec3, out: Vec3[]): void { } function getOBBVertices (c: Vec3, e: Vec3, a1: Vec3, a2: Vec3, a3: Vec3, out: Vec3[]): void { - Vec3.set(out[0], + Vec3.set( + out[0], c.x + a1.x * e.x + a2.x * e.y + a3.x * e.z, c.y + a1.y * e.x + a2.y * e.y + a3.y * e.z, - c.z + a1.z * e.x + a2.z * e.y + a3.z * e.z); - Vec3.set(out[1], + c.z + a1.z * e.x + a2.z * e.y + a3.z * e.z, + ); + Vec3.set( + out[1], c.x - a1.x * e.x + a2.x * e.y + a3.x * e.z, c.y - a1.y * e.x + a2.y * e.y + a3.y * e.z, - c.z - a1.z * e.x + a2.z * e.y + a3.z * e.z); - Vec3.set(out[2], + c.z - a1.z * e.x + a2.z * e.y + a3.z * e.z, + ); + Vec3.set( + out[2], c.x + a1.x * e.x - a2.x * e.y + a3.x * e.z, c.y + a1.y * e.x - a2.y * e.y + a3.y * e.z, - c.z + a1.z * e.x - a2.z * e.y + a3.z * e.z); - Vec3.set(out[3], + c.z + a1.z * e.x - a2.z * e.y + a3.z * e.z, + ); + Vec3.set( + out[3], c.x + a1.x * e.x + a2.x * e.y - a3.x * e.z, c.y + a1.y * e.x + a2.y * e.y - a3.y * e.z, - c.z + a1.z * e.x + a2.z * e.y - a3.z * e.z); - Vec3.set(out[4], + c.z + a1.z * e.x + a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[4], c.x - a1.x * e.x - a2.x * e.y - a3.x * e.z, c.y - a1.y * e.x - a2.y * e.y - a3.y * e.z, - c.z - a1.z * e.x - a2.z * e.y - a3.z * e.z); - Vec3.set(out[5], + c.z - a1.z * e.x - a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[5], c.x + a1.x * e.x - a2.x * e.y - a3.x * e.z, c.y + a1.y * e.x - a2.y * e.y - a3.y * e.z, - c.z + a1.z * e.x - a2.z * e.y - a3.z * e.z); - Vec3.set(out[6], + c.z + a1.z * e.x - a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[6], c.x - a1.x * e.x + a2.x * e.y - a3.x * e.z, c.y - a1.y * e.x + a2.y * e.y - a3.y * e.z, - c.z - a1.z * e.x + a2.z * e.y - a3.z * e.z); - Vec3.set(out[7], + c.z - a1.z * e.x + a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[7], c.x - a1.x * e.x - a2.x * e.y + a3.x * e.z, c.y - a1.y * e.x - a2.y * e.y + a3.y * e.z, - c.z - a1.z * e.x - a2.z * e.y + a3.z * e.z); + c.z - a1.z * e.x - a2.z * e.y + a3.z * e.z, + ); } function getInterval (vertices: any[] | Vec3[], axis: Vec3): number[] { diff --git a/cocos/render-scene/scene/camera.ts b/cocos/render-scene/scene/camera.ts index 31171d10aca..ab8cedbd6c2 100644 --- a/cocos/render-scene/scene/camera.ts +++ b/cocos/render-scene/scene/camera.ts @@ -1032,14 +1032,33 @@ export class Camera { const wndXREye = xr.webXRWindowMap.get(this._window); this._matProj.set(xr.webXRMatProjs[wndXREye]); } else { - Mat4.perspective(this._matProj, this._fov, this._aspect, this._nearClip, this._farClip, - this._fovAxis === CameraFOVAxis.VERTICAL, this._device.capabilities.clipSpaceMinZ, projectionSignY, orientation); + Mat4.perspective( + this._matProj, + this._fov, + this._aspect, + this._nearClip, + this._farClip, + this._fovAxis === CameraFOVAxis.VERTICAL, + this._device.capabilities.clipSpaceMinZ, + projectionSignY, + orientation, + ); } } else { const x = this._orthoHeight * this._aspect; const y = this._orthoHeight; - Mat4.ortho(this._matProj, -x, x, -y, y, this._nearClip, this._farClip, - this._device.capabilities.clipSpaceMinZ, projectionSignY, orientation); + Mat4.ortho( + this._matProj, + -x, + x, + -y, + y, + this._nearClip, + this._farClip, + this._device.capabilities.clipSpaceMinZ, + projectionSignY, + orientation, + ); } Mat4.invert(this._matProjInv, this._matProj); viewProjDirty = true; @@ -1240,10 +1259,12 @@ export class Camera { if (this._proj === CameraProjection.PERSPECTIVE) { // calculate screen pos in far clip plane - Vec3.set(out, + Vec3.set( + out, (screenPos.x - cx) / cw * 2 - 1, (screenPos.y - cy) / ch * 2 - 1, - 1.0); + 1.0, + ); // transform to world const { x, y } = out; @@ -1256,10 +1277,12 @@ export class Camera { Vec3.lerp(out, v_a, out, lerp(this._nearClip / this._farClip, 1, screenPos.z)); } else { - Vec3.set(out, + Vec3.set( + out, (screenPos.x - cx) / cw * 2 - 1, (screenPos.y - cy) / ch * 2 - 1, - screenPos.z * 2 - 1); + screenPos.z * 2 - 1, + ); // transform to world const { x, y } = out; diff --git a/cocos/rendering/custom/compiler.ts b/cocos/rendering/custom/compiler.ts index 651729239d3..da170462e25 100644 --- a/cocos/rendering/custom/compiler.ts +++ b/cocos/rendering/custom/compiler.ts @@ -32,68 +32,50 @@ import { Blit, ClearView, ComputePass, ComputeSubpass, CopyPass, Dispatch, Forma RasterPass, RasterSubpass, RaytracePass, RenderGraph, RenderGraphVisitor, RasterView, ComputeView, RenderQueue, RenderSwapchain, ResolvePass, ResourceGraph, ResourceGraphVisitor, SceneData, SubresourceView } from './render-graph'; import { AccessType, ResourceResidency, SceneFlags } from './types'; +import { hashCombineNum, hashCombineStr } from './define'; -let hashCode = 0; - -function hashCombine (hash): void { - hashCode ^= (hash >>> 0) + 0x9e3779b9 + (hashCode << 6) + (hashCode >> 2); -} - -function hashCombineNum (val: number): void { - const hash = 5381; - hashCombine((hash * 33) ^ val); -} - -function hashCombineStr (str: string): void { - // DJB2 HASH - let hash = 5381; - for (let i = 0; i < str.length; i++) { - hash = (hash * 33) ^ str.charCodeAt(i); - } - hashCombine(hash); -} function genHashValue (pass: RasterPass): void { - hashCode = 0; + let hashCode = 0; for (const [name, raster] of pass.rasterViews) { - hashCombineStr('raster'); - hashCombineStr(name); - hashCombineStr(raster.slotName); - hashCombineNum(raster.accessType); - hashCombineNum(raster.attachmentType); - hashCombineNum(raster.loadOp); - hashCombineNum(raster.storeOp); - hashCombineNum(raster.clearFlags); - hashCombineNum(raster.clearColor.x); - hashCombineNum(raster.clearColor.y); - hashCombineNum(raster.clearColor.z); - hashCombineNum(raster.clearColor.w); - hashCombineNum(raster.slotID); - hashCombineNum(raster.shaderStageFlags); + hashCode = hashCombineStr('raster', hashCode); + hashCode = hashCombineStr(name, hashCode); + hashCode = hashCombineStr(raster.slotName, hashCode); + hashCode = hashCombineNum(raster.accessType, hashCode); + hashCode = hashCombineNum(raster.attachmentType, hashCode); + hashCode = hashCombineNum(raster.loadOp, hashCode); + hashCode = hashCombineNum(raster.storeOp, hashCode); + hashCode = hashCombineNum(raster.clearFlags, hashCode); + hashCode = hashCombineNum(raster.clearColor.x, hashCode); + hashCode = hashCombineNum(raster.clearColor.y, hashCode); + hashCode = hashCombineNum(raster.clearColor.z, hashCode); + hashCode = hashCombineNum(raster.clearColor.w, hashCode); + hashCode = hashCombineNum(raster.slotID, hashCode); + hashCode = hashCombineNum(raster.shaderStageFlags, hashCode); } for (const [name, computes] of pass.computeViews) { - hashCombineStr(name); + hashCode = hashCombineStr(name, hashCode); for (const compute of computes) { - hashCombineStr('compute'); - hashCombineStr(compute.name); - hashCombineNum(compute.accessType); - hashCombineNum(compute.clearFlags); - hashCombineNum(compute.clearValueType); - hashCombineNum(compute.clearValue.x); - hashCombineNum(compute.clearValue.y); - hashCombineNum(compute.clearValue.z); - hashCombineNum(compute.clearValue.w); - hashCombineNum(compute.shaderStageFlags); + hashCode = hashCombineStr('compute', hashCode); + hashCode = hashCombineStr(compute.name, hashCode); + hashCode = hashCombineNum(compute.accessType, hashCode); + hashCode = hashCombineNum(compute.clearFlags, hashCode); + hashCode = hashCombineNum(compute.clearValueType, hashCode); + hashCode = hashCombineNum(compute.clearValue.x, hashCode); + hashCode = hashCombineNum(compute.clearValue.y, hashCode); + hashCode = hashCombineNum(compute.clearValue.z, hashCode); + hashCode = hashCombineNum(compute.clearValue.w, hashCode); + hashCode = hashCombineNum(compute.shaderStageFlags, hashCode); } } - hashCombineNum(pass.width); - hashCombineNum(pass.height); - hashCombineNum(pass.viewport.left); - hashCombineNum(pass.viewport.top); - hashCombineNum(pass.viewport.width); - hashCombineNum(pass.viewport.height); - hashCombineNum(pass.viewport.minDepth); - hashCombineNum(pass.viewport.maxDepth); - hashCombineNum(pass.showStatistics ? 1 : 0); + hashCode = hashCombineNum(pass.width, hashCode); + hashCode = hashCombineNum(pass.height, hashCode); + hashCode = hashCombineNum(pass.viewport.left, hashCode); + hashCode = hashCombineNum(pass.viewport.top, hashCode); + hashCode = hashCombineNum(pass.viewport.width, hashCode); + hashCode = hashCombineNum(pass.viewport.height, hashCode); + hashCode = hashCombineNum(pass.viewport.minDepth, hashCode); + hashCode = hashCombineNum(pass.viewport.maxDepth, hashCode); + hashCode = hashCombineNum(pass.showStatistics ? 1 : 0, hashCode); pass.hashValue = hashCode; } @@ -157,8 +139,10 @@ class PassVisitor implements RenderGraphVisitor { isPreRaster = true; // TODO: Shadow map is rather special, as it will be merged into one pass later, and then this determination can be removed. if (!this._isShadowMap(this.sceneID)) { - assert(currRaster.loadOp === LoadOp.LOAD, - `The resource with name ${input} is being used, and the pass that uses this resource must have loadOp set to 'load'`); + assert( + currRaster.loadOp === LoadOp.LOAD, + `The resource with name ${input} is being used, and the pass that uses this resource must have loadOp set to 'load'`, + ); } } } @@ -287,7 +271,7 @@ class PassVisitor implements RenderGraphVisitor { this._currPass = value; const outputId = this.resID; const outputName = resourceGraph.vertexName(outputId); - let vertID; + let vertID: number; for (const pair of value.copyPairs) { if (pair.target === outputName) { rg.setValid(this.passID, true); @@ -345,7 +329,7 @@ class PassManagerVisitor extends DefaultVisitor { class ResourceVisitor implements ResourceGraphVisitor { private readonly _context: CompilerContext; public resID = 0xFFFFFFFF; - private _passManagerVis; + private _passManagerVis!: PassManagerVisitor; constructor (context: CompilerContext) { this._context = context; } @@ -392,10 +376,12 @@ class ResourceUseContext { computes: Map = new Map(); } class CompilerContext { - set (pipeline: BasicPipeline, + set ( + pipeline: BasicPipeline, resGraph: ResourceGraph, renderGraph: RenderGraph, - layoutGraph: LayoutGraphData): void { + layoutGraph: LayoutGraphData, + ): void { this.pipeline = pipeline; this.resourceGraph = resGraph; this.renderGraph = renderGraph; @@ -417,10 +403,12 @@ export class Compiler { private _pipeline: BasicPipeline; private _layoutGraph: LayoutGraphData; private _visitor: ResourceManagerVisitor; - constructor (pipeline: BasicPipeline, + constructor ( + pipeline: BasicPipeline, renderGraph: RenderGraph, resGraph: ResourceGraph, - layoutGraph: LayoutGraphData) { + layoutGraph: LayoutGraphData, + ) { this._pipeline = pipeline; this._resourceGraph = resGraph; this._layoutGraph = layoutGraph; @@ -447,8 +435,10 @@ export class Compiler { const firstRaster = use.rasters.get(min)!; switch (trait.residency) { case ResourceResidency.PERSISTENT: - assert(firstRaster.loadOp !== LoadOp.DISCARD, - `The loadOp for persistent resources in the top-level pass cannot be set to 'discard'.`); + assert( + firstRaster.loadOp !== LoadOp.DISCARD, + `The loadOp for persistent resources in the top-level pass cannot be set to 'discard'.`, + ); break; case ResourceResidency.MANAGED: assert(firstRaster.loadOp === LoadOp.CLEAR, `The loadOp for Managed resources in the top-level pass can only be set to 'clear'.`); diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index a2a983c9b3b..b131e820357 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -44,9 +44,9 @@ import { Vec2, Vec3, Vec4, macro, geometry, toRadian, cclegacy, assert, nextPow2 import { ImageAsset, Material, Texture2D } from '../../asset/assets'; import { getProfilerCamera, SRGBToLinear } from '../pipeline-funcs'; import { RenderWindow } from '../../render-scene/core/render-window'; -import { RenderData } from './render-graph'; +import { RenderData, RenderGraph } from './render-graph'; import { WebPipeline } from './web-pipeline'; -import { DescriptorSetData } from './layout-graph'; +import { DescriptorSetData, LayoutGraph, LayoutGraphData } from './layout-graph'; import { AABB } from '../../core/geometry'; import { DebugViewCompositeType, DebugViewSingleType } from '../debug-view'; import { ReflectionProbeManager } from '../../3d/reflection-probe/reflection-probe-manager'; @@ -685,7 +685,7 @@ export function buildShadowPass ( queue.addSceneOfCamera( camera, new LightInfo(light, level), - SceneFlags.SHADOW_CASTER, + SceneFlags.SHADOW_CASTER | SceneFlags.OPAQUE_OBJECT | SceneFlags.TRANSPARENT_OBJECT, ); queue.setViewport(new Viewport(area.x, area.y, area.width, area.height)); } @@ -706,6 +706,7 @@ export function buildReflectionProbePasss ( } else if (EDITOR) { for (let faceIdx = 0; faceIdx < probe.bakedCubeTextures.length; faceIdx++) { probe.updateCameraDir(faceIdx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument buildReflectionProbePass(camera, ppl, probe, probe.bakedCubeTextures[faceIdx].window!, faceIdx); } probe.needRender = false; @@ -1127,7 +1128,9 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa const constants = data.constants; const samplers = data.samplers; const textures = data.textures; - const device = cclegacy.director.root.device; + const root = cclegacy.director.root; + const device = root.device; + const pipeline = root.pipeline as WebPipeline; const descriptorSetData = getDescriptorSetDataFromLayout(layout)!; const descriptorSet = descriptorSetData.descriptorSet!; for (const [key, value] of constants) { @@ -1160,7 +1163,7 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa const bindId = getDescBinding(key, descriptorSetData); if (bindId === -1) { continue; } const tex = descriptorSet.getTexture(bindId); - if (!tex || isUpdate) { + if (!tex || (isUpdate && value !== pipeline.defaultTexture)) { bindGlobalDesc(descriptorSet, bindId, value); } } @@ -1168,7 +1171,7 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa const bindId = getDescBinding(key, descriptorSetData); if (bindId === -1) { continue; } const sampler = descriptorSet.getSampler(bindId); - if (!sampler || isUpdate) { + if (!sampler || (isUpdate && value !== pipeline.defaultSampler)) { bindGlobalDesc(descriptorSet, bindId, value); } } @@ -2440,3 +2443,53 @@ export function buildClusterPasses (camera: Camera, pipeline: BasicPipeline): vo buildLightClusterBuildPass(camera, _clusterLightData, ppl); buildLightClusterCullingPass(camera, _clusterLightData, ppl); } + +function hashCombine (hash, currHash: number): number { + return currHash ^= (hash >>> 0) + 0x9e3779b9 + (currHash << 6) + (currHash >> 2); +} + +export function hashCombineNum (val: number, currHash: number): number { + const hash = 5381; + return hashCombine((hash * 33) ^ val, currHash); +} + +export function hashCombineStr (str: string, currHash: number): number { + // DJB2 HASH + let hash = 5381; + for (let i = 0; i < str.length; i++) { + hash = (hash * 33) ^ str.charCodeAt(i); + } + return hashCombine(hash, currHash); +} + +export function bool (val): boolean { + return !!val; +} + +export function getSubpassOrPassID (sceneId: number, rg: RenderGraph, lg: LayoutGraphData): number { + const queueId = rg.getParent(sceneId); + assert(queueId !== 0xFFFFFFFF); + const subpassOrPassID = rg.getParent(queueId); + assert(subpassOrPassID !== 0xFFFFFFFF); + const passId = rg.getParent(subpassOrPassID); + let layoutId = lg.nullVertex(); + // single render pass + if (passId === rg.nullVertex()) { + const layoutName: string = rg.getLayout(subpassOrPassID); + assert(!!layoutName); + layoutId = lg.locateChild(lg.nullVertex(), layoutName); + } else { + const passLayoutName: string = rg.getLayout(passId); + assert(!!passLayoutName); + const passLayoutId = lg.locateChild(lg.nullVertex(), passLayoutName); + assert(passLayoutId !== lg.nullVertex()); + + const subpassLayoutName: string = rg.getLayout(subpassOrPassID); + assert(!!subpassLayoutName); + const subpassLayoutId = lg.locateChild(passLayoutId, subpassLayoutName); + assert(subpassLayoutId !== lg.nullVertex()); + layoutId = subpassLayoutId; + } + assert(layoutId !== lg.nullVertex()); + return layoutId; +} diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 548ab24cc3d..ed08a405181 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -72,7 +72,7 @@ import { import { legacyCC } from '../../core/global-exports'; import { Vec3 } from '../../core/math/vec3'; import { Vec4 } from '../../core/math/vec4'; -import { BatchingSchemes, Pass } from '../../render-scene'; +import { Pass } from '../../render-scene'; import { Camera } from '../../render-scene/scene/camera'; import { ShadowType } from '../../render-scene/scene/shadows'; import { Root } from '../../root'; @@ -126,7 +126,6 @@ import { RenderInfo, RenderObject, WebSceneTask, WebSceneTransversal } from './w import { WebSceneVisitor } from './web-scene-visitor'; import { RenderAdditiveLightQueue } from '../render-additive-light-queue'; import { RenderShadowMapBatchedQueue } from '../render-shadow-map-batched-queue'; -import { PlanarShadowQueue } from '../planar-shadow-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; import { @@ -141,6 +140,7 @@ import { import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; import { builtinResMgr } from '../../asset/asset-manager/builtin-res-mgr'; import { Texture2D } from '../../asset/assets/texture-2d'; +import { SceneCulling } from './scene-culling'; class ResourceVisitor implements ResourceGraphVisitor { name: string; @@ -448,7 +448,7 @@ class BlitDesc { const deferredLitsBufView = context.blit.deferredLitsBufView; this._lightBufferData = context.blit.lightBufferData; this._lightBufferData.fill(0); - const binding = isEnableEffect() ? getDescBindingFromName('CCForwardLight') : UBOForwardLight.BINDING; + // const binding = isEnableEffect() ? getDescBindingFromName('CCForwardLight') : UBOForwardLight.BINDING; this._stageDesc.bindBuffer(UBOForwardLight.BINDING, deferredLitsBufView); } this._stageDesc.bindBuffer(UBOLocal.BINDING, context.blit.emptyLocalUBO); @@ -506,7 +506,7 @@ class DeviceRenderQueue { } this.queueId = id; this._devicePass = devicePass; - if (isEnableEffect()) this._phaseID = cclegacy.rendering.getPhaseID(devicePass.passID, context.renderGraph.getLayout(id) || 'default'); + this._phaseID = cclegacy.rendering.getPhaseID(devicePass.passID, context.renderGraph.getLayout(id)); if (!this._sceneVisitor) { this._sceneVisitor = new WebSceneVisitor( context.commandBuffer, @@ -577,7 +577,6 @@ class SubmitInfo { public renderInstanceQueue: InstancedBuffer[] = []; public opaqueList: RenderInfo[] = []; public transparentList: RenderInfo[] = []; - public planarQueue: PlanarShadowQueue | null = null; // public shadowMap: Map = new Map(); public additiveLight: RenderAdditiveLightQueue | null = null; @@ -604,7 +603,6 @@ class SubmitInfo { this.renderInstanceQueue.length = 0; this.opaqueList.length = 0; this.transparentList.length = 0; - this.planarQueue = null; this._clearShadowMap(); this.additiveLight = null; this.reflectionProbe = null; @@ -1151,182 +1149,17 @@ class DevicePreSceneTask extends WebSceneTask { public start (): void { if (this.graphScene.blit) { this._currentQueue.createBlitDesc(this.graphScene.blit); - return; - } - if (!this.camera) { - return; - } - const devicePass = this._currentQueue.devicePass; - const submitMap = context.submitMap; - let submitInfoMap = submitMap.get(this.camera); - if (submitInfoMap && submitInfoMap.has(this._currentQueue.phaseID)) { - this._submitInfo = submitInfoMap.get(this._currentQueue.phaseID)!; - } else { - if (!submitInfoMap) { - submitInfoMap = new Map(); - submitMap.set(this.camera, submitInfoMap); - } - this._submitInfo = new SubmitInfo(); - submitInfoMap.set(this._currentQueue.phaseID, this._submitInfo); - } - // culling - if ((!isShadowMap(this.graphScene) || (isShadowMap(this.graphScene) && this.graphScene.scene!.light.level === 0)) - && this.camera !== context.cullCamera) { - super.start(); - context.cullCamera = this.camera; - } - - // shadowmap - if (isShadowMap(this.graphScene)) { - const scene = this.graphScene.scene!; - assert(scene.light.light !== null); - let shadowQueue = this._submitInfo.shadowMap.get(this.graphScene.sceneID); - if (!shadowQueue) { - shadowQueue = new RenderShadowMapBatchedQueue(context.pipeline); - this._submitInfo.shadowMap.set(this.graphScene.sceneID, shadowQueue); - } - this.sceneData.shadowFrameBufferMap.set(scene.light.light, devicePass.framebuffer); - shadowQueue.gatherLightPasses(this.camera, scene.light.light, this._cmdBuff, scene.light.level); - return; - } - // reflection probe - if (this.graphScene.scene!.flags & SceneFlags.REFLECTION_PROBE && !this._submitInfo.reflectionProbe) { - this._submitInfo.reflectionProbe = context.pools.addReflectionProbe(); - this._submitInfo.reflectionProbe.clear(); - if (cclegacy.internal.reflectionProbeManager) { - const probes = cclegacy.internal.reflectionProbeManager.getProbes(); - for (let i = 0; i < probes.length; i++) { - if (probes[i].hasFrameBuffer(this._currentQueue.devicePass.framebuffer)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._submitInfo.reflectionProbe.gatherRenderObjects(probes[i], this.camera, this._cmdBuff); - break; - } - } - } - return; - } - const sceneFlag = this._graphScene.scene!.flags; - // If it is not empty, it means that it has been added and will not be traversed. - const isEmpty = !this._submitInfo.opaqueList.length - && !this._submitInfo.transparentList.length - && !this._submitInfo.instances.size; - if (isEmpty) { - for (const ro of this.sceneData.renderObjects) { - const subModels = ro.model.subModels; - for (const subModel of subModels) { - const passes = subModel.passes; - for (const p of passes) { - if (((isEnableEffect()) ? p.phaseID : p.phase) !== this._currentQueue.phaseID) continue; - const batchingScheme = p.batchingScheme; - if (batchingScheme === BatchingSchemes.INSTANCING) { - const instancedBuffer = p.getInstancedBuffer(); - instancedBuffer.merge(subModel, passes.indexOf(p)); - this._submitInfo.instances.add(instancedBuffer); - } else { - this._insertRenderList(ro, subModels.indexOf(subModel), passes.indexOf(p)); - this._insertRenderList(ro, subModels.indexOf(subModel), passes.indexOf(p), true); - } - } - } - } - this._instancedSort(); - } - if (sceneFlag & SceneFlags.DEFAULT_LIGHTING) { - this._submitInfo.additiveLight = context.additiveLight; - validPunctualLightsCulling(context.pipeline, this.camera); - this._submitInfo.additiveLight.gatherLightPasses(this.camera, this._cmdBuff, this._currentQueue.devicePass.layoutName); - } - if (sceneFlag & SceneFlags.PLANAR_SHADOW) { - this._submitInfo.planarQueue = context.planarShadow; - this._submitInfo.planarQueue.gatherShadowPasses(this.camera, this._cmdBuff); - } - if (sceneFlag & SceneFlags.OPAQUE_OBJECT) { this._submitInfo.opaqueList.sort(this._opaqueCompareFn); } - if (sceneFlag & SceneFlags.TRANSPARENT_OBJECT) { this._submitInfo.transparentList.sort(this._transparentCompareFn); } - } - - protected _instancedSort (): void { - let it = this._submitInfo!.instances.values(); - let res = it.next(); - while (!res.done) { - if (!(res.value.pass.blendState.targets[0].blend)) { - this._submitInfo!.renderInstanceQueue.push(res.value); - } - res = it.next(); - } - it = this._submitInfo!.renderInstanceQueue.values(); - res = it.next(); - while (!res.done) { - if (res.value.pass.blendState.targets[0].blend) { - this._submitInfo!.renderInstanceQueue.push(res.value); - } - res = it.next(); - } - } - - protected _insertRenderList (ro: RenderObject, subModelIdx: number, passIdx: number, isTransparent = false): void { - const subModel = ro.model.subModels[subModelIdx]; - const pass: Pass = subModel.passes[passIdx]; - const shader = subModel.shaders[passIdx]; - const currTransparent = pass.blendState.targets[0].blend; - const devicePass = this._currentQueue.devicePass; - const passId = devicePass.passID; - const phase = isEnableEffect() ? this._currentQueue.phaseID // | cclegacy.rendering.getPhaseID(passId, 'planarShadow') - : getPhaseID('default') | getPhaseID('planarShadow'); - if (currTransparent !== isTransparent || !(pass.phaseID & (isTransparent ? phase : this._currentQueue.phaseID))) { - return; - } - const hash = (0 << 30) | pass.priority as number << 16 | subModel.priority as number << 8 | passIdx; - const rp = context.pools.addPassInfo(); - rp.priority = ro.model.priority; - rp.hash = hash; - rp.depth = ro.depth || 0; - rp.shaderId = shader.typedID; - rp.subModel = subModel; - rp.passIdx = passIdx; - if (isTransparent) this._submitInfo!.transparentList.push(rp); - else this._submitInfo!.opaqueList.push(rp); - } - - /** - * @en Comparison sorting function. Opaque objects are sorted by priority -> depth front to back -> shader ID. - * @zh 比较排序函数。不透明对象按优先级 -> 深度由前向后 -> Shader ID 顺序排序。 - */ - protected _opaqueCompareFn (a: RenderInfo, b: RenderInfo): number { - return (a.hash - b.hash) || (a.depth - b.depth) || (a.shaderId - b.shaderId); - } - /** - * @en Comparison sorting function. Transparent objects are sorted by priority -> depth back to front -> shader ID. - * @zh 比较排序函数。半透明对象按优先级 -> 深度由后向前 -> Shader ID 顺序排序。 - */ - protected _transparentCompareFn (a: RenderInfo, b: RenderInfo): number { - return (a.priority - b.priority) || (a.hash - b.hash) || (b.depth - a.depth) || (a.shaderId - b.shaderId); - } - - private _uploadInstanceBuffers (): void { - if (this._currentQueue.isUploadInstance) return; - const it = this._submitInfo!.instances.values(); let res = it.next(); - while (!res.done) { - if (res.value.hasPendingModels) res.value.uploadBuffers(this._cmdBuff); - res = it.next(); } - this._currentQueue.isUploadInstance = true; - } - - protected _updateGlobal (data: RenderData): void { - const devicePass = this._currentQueue.devicePass; - updateGlobalDescBinding(data, isEnableEffect() ? context.renderGraph.getLayout(devicePass.rasterPassInfo.id) : 'default'); - if (!isEnableEffect()) context.pipeline.descriptorSet.update(); } public submit (): void { if (this.graphScene.blit) { this._currentQueue.blitDesc!.update(); - return; } - if (isShadowMap(this.graphScene)) { - return; - } - this._uploadInstanceBuffers(); + // if (isShadowMap(this.graphScene)) { + + // } + // this._uploadInstanceBuffers(); } } @@ -1436,7 +1269,7 @@ class DeviceSceneTask extends WebSceneTask { const count = batch.shaders.length; for (let j = 0; j < count; j++) { const pass = batch.passes[j]; - if (((isEnableEffect()) ? pass.phaseID : pass.phase) !== this._currentQueue.phaseID) continue; + if (pass.phaseID !== this._currentQueue.phaseID) continue; const shader = batch.shaders[j]; const inputAssembler: InputAssembler = batch.inputAssembler!; const pso = PipelineStateManager.getOrCreatePipelineState(deviceManager.gfxDevice, pass, shader, this._renderPass, inputAssembler); @@ -1513,9 +1346,9 @@ class DeviceSceneTask extends WebSceneTask { this.visitor.bindPipelineState(pso); const layoutStage = devicePass.renderLayout; const layoutDesc = layoutStage!.descriptorSet!; - const extResId: number[] = isEnableEffect() ? [] : mergeSrcToTargetDesc(pass.descriptorSet, layoutDesc); + const extResId: number[] = []; // if (isEnableEffect()) this.visitor.bindDescriptorSet(SetIndex.GLOBAL, layoutDesc); - this.visitor.bindDescriptorSet(SetIndex.MATERIAL, isEnableEffect() ? pass.descriptorSet : layoutDesc); + this.visitor.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); this.visitor.bindDescriptorSet(SetIndex.LOCAL, this._currentQueue.blitDesc!.stageDesc!); this.visitor.bindInputAssembler(screenIa); this.visitor.draw(screenIa); @@ -1534,42 +1367,11 @@ class DeviceSceneTask extends WebSceneTask { context.commandBuffer, ); } - - private _recordPlanarShadows (): void { - const devicePass = this._currentQueue.devicePass; - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.planarQueue?.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } protected _updateGlobal (data: RenderData): void { const devicePass = this._currentQueue.devicePass; - updateGlobalDescBinding(data, isEnableEffect() ? context.renderGraph.getLayout(devicePass.rasterPassInfo.id) : 'default'); - if (!isEnableEffect()) context.pipeline.descriptorSet.update(); - } - protected _setMainLightShadowTex (data: RenderData): void { - const graphScene = this.graphScene; - if (graphScene.scene && graphScene.scene.camera) { - const mainLight = graphScene.scene.camera.scene!.mainLight; - const shadowFrameBufferMap = this.sceneData.shadowFrameBufferMap; - if (mainLight && shadowFrameBufferMap.has(mainLight)) { - const shadowAttrID = context.layoutGraph.attributeIndex.get('cc_shadowMap'); - const defaultTex = builtinResMgr.get('default-texture').getGFXTexture()!; - for (const [key, value] of data.textures) { - if (key === shadowAttrID) { - const tex = data.textures.get(shadowAttrID); - if (tex === defaultTex) { - data.textures.set(key, shadowFrameBufferMap.get(mainLight)!.colorTextures[0]!); - } - return; - } - } - } - } + updateGlobalDescBinding(data, context.renderGraph.getLayout(devicePass.rasterPassInfo.id)); } + protected _updateRenderData (): void { if (this._currentQueue.isUpdateUBO) return; const devicePass = this._currentQueue.devicePass; @@ -1580,18 +1382,17 @@ class DeviceSceneTask extends WebSceneTask { // CCCamera, CCShadow, CCCSM const queueId = this._currentQueue.queueId; const queueRenderData = context.renderGraph.getData(queueId)!; - this._setMainLightShadowTex(queueRenderData); this._updateGlobal(queueRenderData); - if (isEnableEffect()) { - const layoutName = context.renderGraph.getLayout(rasterId); - const descSetData = getDescriptorSetDataFromLayout(layoutName); - mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet, true); - } + + const layoutName = context.renderGraph.getLayout(rasterId); + const descSetData = getDescriptorSetDataFromLayout(layoutName); + mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet, true); this._currentQueue.isUpdateUBO = true; } public submit (): void { const devicePass = this._currentQueue.devicePass; const queueViewport = this._currentQueue.viewport; + const sceneCulling = context.culling; this._updateRenderData(); if (queueViewport) { this.visitor.setViewport(queueViewport); @@ -1615,30 +1416,23 @@ class DeviceSceneTask extends WebSceneTask { this._recordBlit(); return; } - if (isShadowMap(this.graphScene)) { - this._recordShadowMap(); - return; - } + const renderQueueDesc = sceneCulling.sceneQueryIndex.get(this.graphScene.sceneID)!; + const renderQueue = sceneCulling.renderQueues[renderQueueDesc.renderQueueTarget]; const graphSceneData = this.graphScene.scene!; if (graphSceneData.flags & SceneFlags.OPAQUE_OBJECT || graphSceneData.flags & SceneFlags.CUTOUT_OBJECT) { - this._recordOpaqueList(); - } - if (graphSceneData.flags & SceneFlags.DRAW_INSTANCING) { - this._recordInstences(); - } - if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) { - this._recordAdditiveLights(); - } - this.visitor.bindDescriptorSet( - SetIndex.GLOBAL, - context.pipeline.descriptorSet, - ); - if (graphSceneData.flags & SceneFlags.PLANAR_SHADOW) { - this._recordPlanarShadows(); + renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); } + renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); + renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); + // if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) { + // this._recordAdditiveLights(); + // } + // this.visitor.bindDescriptorSet(SetIndex.GLOBAL, + // context.pipeline.descriptorSet); if (graphSceneData.flags & SceneFlags.TRANSPARENT_OBJECT) { - this._recordTransparentList(); + // this._recordTransparentList(); + renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); } if (graphSceneData.flags & SceneFlags.GEOMETRY) { this.camera!.geometryRenderer?.render( @@ -1908,11 +1702,12 @@ class ExecutorContext { this.height = height; this.additiveLight = new RenderAdditiveLightQueue(pipeline); this.shadowMapBatched = new RenderShadowMapBatchedQueue(pipeline); - this.planarShadow = new PlanarShadowQueue(pipeline); this.pools = new ExecutorPools(this); this.blit = new BlitInfo(this); + this.culling = new SceneCulling(); } reset (): void { + this.culling.clear(); this.pools.reset(); this.cullCamera = null; for (const infoMap of this.submitMap) { @@ -1936,10 +1731,10 @@ class ExecutorContext { readonly ubo: PipelineUBO; readonly additiveLight: RenderAdditiveLightQueue; readonly shadowMapBatched: RenderShadowMapBatchedQueue; - readonly planarShadow: PlanarShadowQueue; readonly submitMap: Map> = new Map>(); readonly pools: ExecutorPools; readonly blit: BlitInfo; + readonly culling: SceneCulling; renderGraph: RenderGraph; width: number; height: number; @@ -1998,8 +1793,10 @@ export class Executor { execute (rg: RenderGraph): void { context.renderGraph = rg; context.reset(); - this._removeDeviceResource(); const cmdBuff = context.commandBuffer; + context.culling.buildRenderQueues(rg, context.layoutGraph, context.pipelineSceneData); + context.culling.uploadInstancing(cmdBuff); + this._removeDeviceResource(); cmdBuff.begin(); if (!this._visitor) this._visitor = new RenderVisitor(); depthFirstSearch(this._visitor.graphView, this._visitor, this._visitor.colorMap); diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts new file mode 100644 index 00000000000..f4960124c86 --- /dev/null +++ b/cocos/rendering/custom/scene-culling.ts @@ -0,0 +1,420 @@ +import { Vec3, assert } from '../../core'; +import { Frustum, intersect, AABB } from '../../core/geometry'; +import { CommandBuffer } from '../../gfx'; +import { BatchingSchemes, Pass, RenderScene } from '../../render-scene'; +import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, SKYBOX_FLAG, ShadowType, SpotLight } from '../../render-scene/scene'; +import { Node } from '../../scene-graph'; +import { PipelineSceneData } from '../pipeline-scene-data'; +import { hashCombineStr, getSubpassOrPassID, bool } from './define'; +import { LayoutGraphData } from './layout-graph'; +import { RenderGraph, RenderGraphValue, SceneData } from './render-graph'; +import { SceneFlags } from './types'; +import { RenderQueue, RenderQueueDesc } from './web-pipeline-types'; + +function computeCullingKey (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number): number { + let hashCode = 0; + if (camera) { + // camera + hashCode = hashCombineStr(`u${camera.node.uuid}`, hashCode); + hashCode = hashCombineStr(`p${camera.priority}`, hashCode); + hashCode = hashCombineStr(`v${camera.visibility}`, hashCode); + hashCode = hashCombineStr(`f${camera.clearFlag}`, hashCode); + hashCode = hashCombineStr(`cx${camera.clearColor.x}cy${camera.clearColor.y}cz${camera.clearColor.z}cw${camera.clearColor.w}`, hashCode); + hashCode = hashCombineStr(`cd${camera.clearDepth}cs${camera.clearStencil}`, hashCode); + hashCode = hashCombineStr(`pj${camera.projectionType}`, hashCode); + hashCode = hashCombineStr(`fa${camera.fovAxis}`, hashCode); + hashCode = hashCombineStr(`fov${camera.fov}`, hashCode); + hashCode = hashCombineStr(`n${camera.nearClip}`, hashCode); + hashCode = hashCombineStr(`far${camera.farClip}`, hashCode); + hashCode = hashCombineStr(`apt${camera.aperture}`, hashCode); + hashCode = hashCombineStr(`sht${camera.shutter}`, hashCode); + hashCode = hashCombineStr(`iso${camera.iso}`, hashCode); + hashCode = hashCombineStr(`rx${camera.viewport.x}ry${camera.viewport.y}rw${camera.viewport.width}rh${camera.viewport.height}`, hashCode); + hashCode = hashCombineStr(`upp${camera.usePostProcess}`, hashCode); + } + // light + if (light) { + hashCode = hashCombineStr(`u${light.node!.uuid}`, hashCode); + // hashCode = hashCombineStr(`cx${light.finalColor.x}cy${light.finalColor.y}cz${light.finalColor.z}`, hashCode); + // hashCode = hashCombineStr(`ct${light.useColorTemperature}`, hashCode); + // hashCode = hashCombineStr(`ctv${light.colorTemperature}`, hashCode); + // hashCode = hashCombineStr(`vis${light.visibility}`, hashCode); + // hashCode = hashCombineStr(`tp${light.type}`, hashCode); + // switch (light.type) { + // case LightType.DIRECTIONAL: + // hashCode = hashCombineStr(`${(light as DirectionalLight).illuminance}`, hashCode); + // break; + // default: + // } + } + hashCode = hashCombineStr(`cast${castShadows}`, hashCode); + hashCode = hashCombineStr(`level${lightLevel}`, hashCode); + return hashCode; +} + +class CullingKey { + camera: Camera | null; + light: Light | null; + castShadows = false; + lightLevel = 0xffffffff; + constructor (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number) { + this.camera = camera; + this.light = light; + this.castShadows = castShadows; + this.lightLevel = lightLevel; + } +} + +let pSceneData: PipelineSceneData; + +class CullingQueries { + // key: hash val + culledResultIndex: Map = new Map(); + cullingKeyResult: Map = new Map(); +} + +function isNodeVisible (node: Node, visibility: number): boolean { + return node && ((visibility & node.layer) === node.layer); +} + +function isModelVisible (model: Model, visibility: number): boolean { + return !!(visibility & model.visFlags); +} +const transWorldBounds = new AABB(); +function isFrustumVisible (model: Model, frustum: Readonly, castShadow: boolean): boolean { + const modelWorldBounds = model.worldBounds; + if (!modelWorldBounds) { + return false; + } + transWorldBounds.copy(modelWorldBounds); + const shadows = pSceneData.shadows; + if (shadows.type === ShadowType.Planar && castShadow) { + AABB.transform(transWorldBounds, modelWorldBounds, shadows.matLight); + } + return !intersect.aabbFrustum(transWorldBounds, frustum); +} + +function sceneCulling ( + skyboxModelToSkip: Model | null, + scene: RenderScene, + camera: Camera, + camOrLightFrustum: Readonly, + castShadow: boolean, + models: Array, +): void { + const visibility = camera.visibility; + for (const model of scene.models) { + assert(!!model); + if (!model.enabled || model === skyboxModelToSkip || (castShadow && !model.castShadow)) { + continue; + } + if (scene && scene.isCulledByLod(camera, model)) { + continue; + } + + if (isNodeVisible(model.node, visibility) + || isModelVisible(model, visibility)) { + // frustum culling + if (isFrustumVisible(model, camOrLightFrustum, castShadow)) { + continue; + } + + models.push(model); + } + } +} + +function isBlend (pass: Pass): boolean { + let bBlend = false; + for (const target of pass.blendState.targets) { + if (target.blend) { + bBlend = true; + } + } + return bBlend; +} + +function computeSortingDepth (camera: Camera, model: Model): number { + let depth = 0; + if (model.node) { + const node = model.transform; + const tempVec3 = new Vec3(); + const position = Vec3.subtract(tempVec3, node.worldPosition, camera.position); + depth = position.dot(camera.forward); + } + return depth; +} + +function addRenderObject ( + phaseLayoutId: number, + isDrawOpaqueOrMask: boolean, + isDrawBlend: boolean, + isDrawShadowCaster: boolean, + camera: Camera, + model: Model, + queue: RenderQueue, +): void { + const subModels = model.subModels; + const subModelCount = subModels.length; + for (let subModelIdx = 0; subModelIdx < subModelCount; ++subModelIdx) { + const subModel = subModels[subModelIdx]; + const passes = subModel.passes; + const passCount = passes.length; + for (let passIdx = 0; passIdx < passCount; ++passIdx) { + const pass = passes[passIdx]; + // check phase + const phaseAllowed = phaseLayoutId === pass.phaseID; + if (!phaseAllowed) { + continue; + } + // check scene flags + const is_blend = isBlend(pass); + const isOpaqueOrMask = !is_blend; + if (!isDrawShadowCaster) { + if (!isDrawBlend && is_blend) { + // skip transparent object + continue; + } + if (!isDrawOpaqueOrMask && isOpaqueOrMask) { + // skip opaque object + continue; + } + } + + // add object to queue + if (pass.batchingScheme === BatchingSchemes.INSTANCING) { + const instancedBuffer = pass.getInstancedBuffer(); + instancedBuffer.merge(subModel, passIdx); + if (is_blend) { + queue.transparentInstancingQueue.add(instancedBuffer); + } else { + queue.opaqueInstancingQueue.add(instancedBuffer); + } + } else { + const depth = computeSortingDepth(camera, model); + if (is_blend) { + queue.transparentQueue.add(model, depth, subModelIdx, passIdx); + } else { + queue.opaqueQueue.add(model, depth, subModelIdx, passIdx); + } + } + } + } +} + +export class SceneCulling { + sceneQueries: Map = new Map(); + culledResults: Array> = new Array>(); + renderQueues: Array = new Array(); + sceneQueryIndex: Map = new Map(); + // source id + numCullingQueries = 0; + // target id + numRenderQueues = 0; + layoutGraph; + renderGraph; + clear (): void { + this.sceneQueries.clear(); + for (const c of this.culledResults) { + c.length = 0; + } + this.culledResults.length = 0; + for (const q of this.renderQueues) { + q.clear(); + } + this.renderQueues.length = 0; + this.sceneQueryIndex.clear(); + this.numCullingQueries = 0; + this.numRenderQueues = 0; + } + + buildRenderQueues (rg: RenderGraph, lg: LayoutGraphData, pplSceneData: PipelineSceneData): void { + this.layoutGraph = lg; + this.renderGraph = rg; + pSceneData = pplSceneData; + this.collectCullingQueries(rg, lg); + this.batchCulling(pplSceneData); + this.fillRenderQueues(rg, pplSceneData); + } + + private getOrCreateSceneCullingQuery (sceneData: SceneData): number { + const scene = sceneData.scene!; + let queries = this.sceneQueries.get(scene); + if (!queries) { + this.sceneQueries.set(scene, new CullingQueries()); + queries = this.sceneQueries.get(scene); + } + const castShadow = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); + const key = computeCullingKey(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level); + const cullNum = queries!.culledResultIndex.get(key); + if (cullNum !== undefined) { + return cullNum; + } + const soureceID = this.numCullingQueries++; + if (this.numCullingQueries > this.culledResults.length) { + assert(this.numCullingQueries === (this.culledResults.length + 1)); + this.culledResults.push([]); + } + queries!.culledResultIndex.set(key, soureceID); + queries!.cullingKeyResult.set(key, new CullingKey(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level)); + return soureceID; + } + + private createRenderQueue (sceneFlags: SceneFlags, subpassOrPassLayoutID: number): number { + const targetID = this.numRenderQueues++; + if (this.numRenderQueues > this.renderQueues.length) { + assert(this.numRenderQueues === (this.renderQueues.length + 1)); + this.renderQueues.push(new RenderQueue()); + } + assert(targetID < this.renderQueues.length); + const rq = this.renderQueues[targetID]; + rq.sceneFlags = sceneFlags; + rq.subpassOrPassLayoutID = subpassOrPassLayoutID; + return targetID; + } + + private collectCullingQueries (rg: RenderGraph, lg: LayoutGraphData): void { + for (const v of rg.vertices()) { + if (!rg.holds(RenderGraphValue.Scene, v) || !rg.getValid(v)) { + continue; + } + const sceneData = rg.getScene(v); + if (!sceneData.scene) { + assert(!!sceneData.scene); + continue; + } + const sourceID = this.getOrCreateSceneCullingQuery(sceneData); + const layoutID = getSubpassOrPassID(v, rg, lg); + const targetID = this.createRenderQueue(sceneData.flags, layoutID); + + const lightType = sceneData.light.light ? sceneData.light.light.type : LightType.UNKNOWN; + // add render queue to query source + this.sceneQueryIndex.set(v, new RenderQueueDesc(sourceID, targetID, lightType)); + } + } + + uploadInstancing (cmdBuffer: CommandBuffer): void { + for (let queueID = 0; queueID !== this.numRenderQueues; ++queueID) { + assert(this.numRenderQueues <= this.renderQueues.length); + const queue = this.renderQueues[queueID]; + queue.opaqueInstancingQueue.uploadBuffers(cmdBuffer); + queue.transparentInstancingQueue.uploadBuffers(cmdBuffer); + } + } + + private batchCulling (pplSceneData: PipelineSceneData): void { + const skybox = pplSceneData.skybox; + const skyboxModelToSkip = skybox ? skybox.model : null; + for (const [scene, queries] of this.sceneQueries) { + assert(!!scene); + for (const [key, sourceID] of queries.culledResultIndex) { + const cullingKey = queries.cullingKeyResult.get(key)!; + assert(!!cullingKey.camera); + assert(cullingKey.camera.scene === scene); + const camera = cullingKey.camera; + const light = cullingKey.light; + const level = cullingKey.lightLevel; + const castShadow = cullingKey.castShadows; + assert(sourceID < this.culledResults.length); + const models = this.culledResults[sourceID]; + if (light) { + switch (light.type) { + case LightType.SPOT: + sceneCulling(skyboxModelToSkip, scene, camera, (light as SpotLight).frustum, castShadow, models); + break; + case LightType.DIRECTIONAL: { + const csmLayers = pplSceneData.csmLayers; + const mainLight: DirectionalLight = light as DirectionalLight; + const csmLevel = mainLight.csmLevel; + let frustum: Readonly; + const shadows = pplSceneData.shadows; + if (shadows.type === ShadowType.Planar) { + frustum = camera.frustum; + } else { + if (shadows.enabled && shadows.type === ShadowType.ShadowMap && mainLight && mainLight.node) { + // pplSceneData.updateShadowUBORange(UBOShadow.SHADOW_COLOR_OFFSET, shadows.shadowColor); + csmLayers.update(pplSceneData, camera); + } + + if (mainLight.shadowFixedArea || csmLevel === CSMLevel.LEVEL_1) { + frustum = csmLayers.specialLayer.validFrustum; + } else { + frustum = csmLayers.layers[level].validFrustum; + } + } + sceneCulling(skyboxModelToSkip, scene, camera, frustum, castShadow, models); + } + break; + default: + } + } else { + sceneCulling(skyboxModelToSkip, scene, camera, camera.frustum, castShadow, models); + } + } + } + } + + private fillRenderQueues (rg: RenderGraph, pplSceneData: PipelineSceneData): void { + const skybox = pplSceneData.skybox; + for (const [sceneId, desc] of this.sceneQueryIndex) { + assert(rg.holds(RenderGraphValue.Scene, sceneId)); + const sourceId = desc.culledSource; + const targetId = desc.renderQueueTarget; + const sceneData = rg.getScene(sceneId); + const isDrawBlend = bool(sceneData.flags & SceneFlags.TRANSPARENT_OBJECT); + const isDrawOpaqueOrMask = bool(sceneData.flags & (SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT)); + const isDrawShadowCaster = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); + if (!isDrawShadowCaster && !isDrawBlend && !isDrawOpaqueOrMask) { + continue; + } + // render queue info + const renderQueueId = rg.getParent(sceneId); + assert(rg.holds(RenderGraphValue.Queue, renderQueueId)); + const graphRenderQueue = rg.getQueue(renderQueueId); + const phaseLayoutId = graphRenderQueue.phaseID; + assert(phaseLayoutId !== this.layoutGraph.nullVertex()); + + // culling source + assert(sourceId < this.culledResults.length); + const sourceModels = this.culledResults[sourceId]; + + // queue target + assert(targetId < this.renderQueues.length); + const renderQueue = this.renderQueues[targetId]; + assert(renderQueue.empty()); + + // skybox + const camera = sceneData.camera; + assert(!!camera); + if (!bool(sceneData.flags & SceneFlags.SHADOW_CASTER) + && skybox && skybox.enabled + && (camera.clearFlag & SKYBOX_FLAG)) { + assert(!!skybox.model); + const model = skybox.model; + const node = model.node; + let depth = 0; + if (node) { + const tempVec3 = new Vec3(); + Vec3.subtract(tempVec3, node.worldPosition, camera.position); + depth = tempVec3.dot(camera.forward); + } + renderQueue.opaqueQueue.add(model, depth, 0, 0); + } + + // fill render queue + for (const model of sourceModels) { + addRenderObject( + phaseLayoutId, + isDrawOpaqueOrMask, + isDrawBlend, + isDrawShadowCaster, + camera, + model, + renderQueue, + ); + } + // post-processing + renderQueue.sort(); + } + } +} diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts new file mode 100644 index 00000000000..c41128cefd4 --- /dev/null +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -0,0 +1,234 @@ +import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; +import { RenderScene } from '../../render-scene'; +import { Camera, Light, LightType, Model, SubModel } from '../../render-scene/scene'; +import { SetIndex } from '../define'; +import { InstancedBuffer } from '../instanced-buffer'; +import { PipelineStateManager } from '../pipeline-state-manager'; +import { SceneFlags } from './types'; + +export class DrawInstance { + subModel: SubModel | null; + priority: number; + hash: number; + depth: number; + shaderID: number; + passIndex: number; + + constructor ( + subModel: SubModel | null = null, + priority = 0, + hash = 0, + depth = 0, + shaderID = 0, + passIndex = 0, + ) { + this.subModel = subModel; + this.priority = priority; + this.hash = hash; + this.depth = depth; + this.shaderID = shaderID; + this.passIndex = passIndex; + } +} + +export class RenderDrawQueue { + instances: Array = new Array(); + + add (model: Model, depth: number, subModelIdx: number, passIdx: number): void { + const subModel = model.subModels[subModelIdx]; + const pass = subModel.passes[passIdx]; + const passPriority = pass.priority; + const modelPriority = subModel.priority; + const shaderId = subModel.shaders[passIdx].typedID; + const hash = (0 << 30) | (passPriority as number << 16) | (modelPriority as number << 8) | passIdx; + const priority = model.priority; + + this.instances.push(new DrawInstance(subModel, priority, hash, depth, shaderId, passIdx)); + } + /** + * @en Comparison sorting function. Opaque objects are sorted by priority -> depth front to back -> shader ID. + * @zh 比较排序函数。不透明对象按优先级 -> 深度由前向后 -> Shader ID 顺序排序。 + */ + sortOpaqueOrCutout (): void { + this.instances.sort((lhs: DrawInstance, rhs: DrawInstance) => { + if (lhs.hash !== rhs.hash) { + return lhs.hash - rhs.hash; + } + if (lhs.depth !== rhs.depth) { + return lhs.depth - rhs.depth; + } + return lhs.shaderID - rhs.shaderID; + }); + } + /** + * @en Comparison sorting function. Transparent objects are sorted by priority -> depth back to front -> shader ID. + * @zh 比较排序函数。半透明对象按优先级 -> 深度由后向前 -> Shader ID 顺序排序。 + */ + sortTransparent (): void { + this.instances.sort((lhs: DrawInstance, rhs: DrawInstance) => { + if (lhs.priority !== rhs.priority) { + return lhs.priority - rhs.priority; + } + if (lhs.hash !== rhs.hash) { + return lhs.hash - rhs.hash; + } + if (lhs.depth !== rhs.depth) { + return rhs.depth - lhs.depth; // 注意此处的差值顺序,为了按照降序排列 + } + return lhs.shaderID - rhs.shaderID; + }); + } + + recordCommandBuffer ( + device: Device, + renderPass: RenderPass, + cmdBuffer: CommandBuffer, + ): void { + for (const instance of this.instances) { + const subModel = instance.subModel!; + + const passIdx = instance.passIndex; + const inputAssembler = subModel.inputAssembler; + const pass = subModel.passes[passIdx]; + const shader = subModel.shaders[passIdx]; + const pso = PipelineStateManager.getOrCreatePipelineState(device, pass, shader, renderPass, inputAssembler); + + cmdBuffer.bindPipelineState(pso); + cmdBuffer.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); + cmdBuffer.bindDescriptorSet(SetIndex.LOCAL, subModel.descriptorSet); + cmdBuffer.bindInputAssembler(inputAssembler); + cmdBuffer.draw(inputAssembler); + } + } +} + +export class RenderInstancingQueue { + batches: Set = new Set(); + sortedBatches: Array = new Array(); + + add (instancedBuffer: InstancedBuffer): void { + this.batches.add(instancedBuffer); + } + + sort (): void { + this.sortedBatches = Array.from(this.batches); + } + + uploadBuffers (cmdBuffer: CommandBuffer): void { + for (const instanceBuffer of this.batches) { + if (instanceBuffer.hasPendingModels) { + instanceBuffer.uploadBuffers(cmdBuffer); + } + } + } + + recordCommandBuffer ( + renderPass: RenderPass, + cmdBuffer: CommandBuffer, + ds: DescriptorSet | null = null, + offset = 0, + dynamicOffsets: number[] | null = null, + ): void { + const renderQueue = this.sortedBatches; + for (const instanceBuffer of renderQueue) { + if (!instanceBuffer.hasPendingModels) { + continue; + } + const instances = instanceBuffer.instances; + const drawPass = instanceBuffer.pass; + cmdBuffer.bindDescriptorSet(SetIndex.MATERIAL, drawPass.descriptorSet); + let lastPSO: PipelineState | null = null; + for (const instance of instances) { + if (!instance.count) { + continue; + } + const pso = PipelineStateManager.getOrCreatePipelineState( + deviceManager.gfxDevice, + drawPass, + instance.shader!, + renderPass, + instance.ia, + ); + if (lastPSO !== pso) { + cmdBuffer.bindPipelineState(pso); + lastPSO = pso; + } + if (ds) { + cmdBuffer.bindDescriptorSet(SetIndex.GLOBAL, ds, [offset]); + } + if (dynamicOffsets) { + cmdBuffer.bindDescriptorSet(SetIndex.LOCAL, instance.descriptorSet, dynamicOffsets); + } else { + cmdBuffer.bindDescriptorSet( + SetIndex.LOCAL, + instance.descriptorSet, + instanceBuffer.dynamicOffsets, + ); + } + cmdBuffer.bindInputAssembler(instance.ia); + cmdBuffer.draw(instance.ia); + } + } + } +} + +export class RenderQueueDesc { + culledSource: number; + renderQueueTarget: number; + lightType: LightType; + + constructor ( + culledSourceIn = 0xFFFFFFFF, + renderQueueTargetIn = 0xFFFFFFFF, + lightTypeIn: LightType = LightType.UNKNOWN, + ) { + this.culledSource = culledSourceIn; + this.renderQueueTarget = renderQueueTargetIn; + this.lightType = lightTypeIn; + } +} + +export class RenderQueue { + opaqueQueue: RenderDrawQueue = new RenderDrawQueue(); + transparentQueue: RenderDrawQueue = new RenderDrawQueue(); + opaqueInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); + transparentInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); + sceneFlags: SceneFlags = SceneFlags.NONE; + subpassOrPassLayoutID = 0xffffffff; + + sort (): void { + this.opaqueQueue.sortOpaqueOrCutout(); + this.transparentQueue.sortTransparent(); + this.opaqueInstancingQueue.sort(); + this.transparentInstancingQueue.sort(); + } + + private _clearInstances (instances: Set): void { + const it = instances.values(); let res = it.next(); + while (!res.done) { + res.value.clear(); + res = it.next(); + } + instances.clear(); + } + + clear (): void { + this.opaqueQueue.instances.length = 0; + this.transparentQueue.instances.length = 0; + this._clearInstances(this.opaqueInstancingQueue.batches); + this.opaqueInstancingQueue.sortedBatches.length = 0; + this._clearInstances(this.transparentInstancingQueue.batches); + this.transparentInstancingQueue.sortedBatches.length = 0; + this.sceneFlags = SceneFlags.NONE; + this.subpassOrPassLayoutID = 0xFFFFFFFF; + } + + empty (): boolean { + return this.opaqueQueue.instances.length === 0 + && this.transparentQueue.instances.length === 0 + && this.opaqueInstancingQueue.batches.size === 0 + && this.opaqueInstancingQueue.sortedBatches.length === 0 + && this.transparentInstancingQueue.batches.size === 0 + && this.transparentInstancingQueue.sortedBatches.length === 0; + } +} diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index c1bac8ca455..08e171ab45c 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -304,7 +304,11 @@ function setShadowUBOLightView ( const pipeline = (director.root as Root).pipeline; const device = pipeline.device; const sceneData = pipeline.pipelineSceneData; + const shadowInfo = sceneData.shadows; + if (shadowInfo.type === ShadowType.Planar) { + return; + } const csmLayers = sceneData.csmLayers; const packing = supportsR32FloatTexture(device) ? 0.0 : 1.0; const cap = pipeline.device.capabilities; @@ -758,6 +762,7 @@ function setTextureUBOView (setter: WebSetter, camera: Camera | null, cfg: Reado const skybox = cfg.skybox; const director = cclegacy.director; const root = director.root; + const pipeline = root.pipeline as WebPipeline; if (skybox.reflectionMap) { const texture = skybox.reflectionMap.getGFXTexture()!; const sampler: Sampler = root.device.getSampler(skybox.reflectionMap.getSamplerInfo()); @@ -779,18 +784,17 @@ function setTextureUBOView (setter: WebSetter, camera: Camera | null, cfg: Reado setter.setTexture('cc_diffuseMap', texture); setter.setSampler('cc_diffuseMap', sampler); } - const pointSampler: Sampler = root.device.getSampler(_samplerPointInfo); if (!setter.hasSampler('cc_shadowMap')) { - setter.setSampler('cc_shadowMap', pointSampler); + setter.setSampler('cc_shadowMap', pipeline.defaultSampler); } if (!setter.hasTexture('cc_shadowMap')) { - setter.setTexture('cc_shadowMap', builtinResMgr.get('default-texture').getGFXTexture()!); + setter.setTexture('cc_shadowMap', pipeline.defaultTexture); } if (!setter.hasSampler('cc_spotShadowMap')) { - setter.setSampler('cc_spotShadowMap', pointSampler); + setter.setSampler('cc_spotShadowMap', pipeline.defaultSampler); } if (!setter.hasTexture('cc_spotShadowMap')) { - setter.setTexture('cc_spotShadowMap', builtinResMgr.get('default-texture').getGFXTexture()!); + setter.setTexture('cc_spotShadowMap', pipeline.defaultTexture); } } @@ -989,11 +993,12 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB throw new Error('Method not implemented.'); } addQueue (hint: QueueHint = QueueHint.RENDER_OPAQUE, layoutName = 'default'): RenderQueueBuilder { + const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); if (DEBUG) { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); assert(layoutId !== 0xFFFFFFFF); } const queue = new RenderQueue(hint); + queue.phaseID = layoutId; const data = new RenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); return new WebRenderQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); @@ -1129,11 +1134,12 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR return result; } addQueue (hint: QueueHint = QueueHint.RENDER_OPAQUE, layoutName = 'default'): WebRenderQueueBuilder { + const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); if (DEBUG) { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); assert(layoutId !== 0xFFFFFFFF); } const queue = new RenderQueue(hint); + queue.phaseID = layoutId; const data = new RenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); return new WebRenderQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); @@ -1283,11 +1289,12 @@ export class WebComputePassBuilder extends WebSetter implements ComputePassBuild throw new Error('Method not implemented.'); } addQueue (layoutName = 'default'): WebComputeQueueBuilder { + const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); if (DEBUG) { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); assert(layoutId !== 0xFFFFFFFF); } const queue = new RenderQueue(); + queue.phaseID = layoutId; const data = new RenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); return new WebComputeQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); @@ -1556,6 +1563,14 @@ export class WebPipeline implements BasicPipeline { return this._globalDescSetData; } + get defaultSampler (): Sampler { + return this._defaultSampler; + } + + get defaultTexture (): Texture { + return builtinResMgr.get('default-texture').getGFXTexture()!; + } + private _compileMaterial (): void { this._copyPassMat.initialize({ effectName: 'pipeline/copy-pass', @@ -1587,7 +1602,9 @@ export class WebPipeline implements BasicPipeline { // 0: SHADOWMAP_LINER_DEPTH_OFF, 1: SHADOWMAP_LINER_DEPTH_ON. const isLinear = this._device.gfxAPI === API.WEBGL ? 1 : 0; this.setMacroInt('CC_SHADOWMAP_USE_LINEAR_DEPTH', isLinear); - + const director: Director = cclegacy.director; + const root: Root = director.root!; + this._defaultSampler = root.device.getSampler(_samplerPointInfo); // 0: UNIFORM_VECTORS_LESS_EQUAL_64, 1: UNIFORM_VECTORS_GREATER_EQUAL_125. this.pipelineSceneData.csmSupported = this.device.capabilities.maxFragmentUniformVectors >= (WebPipeline.CSM_UNIFORM_VECTORS + WebPipeline.GLOBAL_UNIFORM_VECTORS); @@ -1998,6 +2015,7 @@ export class WebPipeline implements BasicPipeline { private _copyPassMat: Material = new Material(); private _device!: Device; private _globalDSManager!: GlobalDSManager; + private _defaultSampler!: Sampler; private _globalDescriptorSet: DescriptorSet | null = null; private _globalDescriptorSetInfo: DescriptorSetInfo | null = null; private _globalDescriptorSetLayout: DescriptorSetLayout | null = null; diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index ef9f478d28e..e81630d80d2 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -11,7 +11,7 @@ import { ShadowPass } from './shadow-pass'; export class ForwardPass extends BasePass { name = 'ForwardPass'; - outputNames = ['ForwardColor', 'ForwardDS'] + outputNames = ['ForwardColor', 'ForwardDS']; enableInAllEditorCamera = true; depthBufferShadingScale = 1; @@ -70,11 +70,21 @@ export class ForwardPass extends BasePass { } } pass.addQueue(QueueHint.RENDER_OPAQUE) - .addSceneOfCamera(camera, + .addSceneOfCamera( + camera, new LightInfo(), - SceneFlags.OPAQUE_OBJECT | SceneFlags.PLANAR_SHADOW | SceneFlags.CUTOUT_OBJECT - | SceneFlags.DEFAULT_LIGHTING | SceneFlags.DRAW_INSTANCING | SceneFlags.GEOMETRY); - + SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT + | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, + ); + if (camera.scene?.mainLight) { + pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'planar-shadow') + .addSceneOfCamera( + camera, + new LightInfo(camera.scene?.mainLight), + SceneFlags.TRANSPARENT_OBJECT | SceneFlags.SHADOW_CASTER + | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, + ); + } passContext.forwardPass = this; } } diff --git a/cocos/rendering/post-process/passes/skin-pass.ts b/cocos/rendering/post-process/passes/skin-pass.ts index bcbc60fdc82..7da7dbaacff 100644 --- a/cocos/rendering/post-process/passes/skin-pass.ts +++ b/cocos/rendering/post-process/passes/skin-pass.ts @@ -120,7 +120,7 @@ export class SSSSBlurData { const o = -range + i * step; const sign = o < 0.0 ? -1.0 : 1.0; // eslint-disable-next-line no-restricted-properties - this._kernel[i].w = range * sign * Math.abs(Math.pow(o, EXPONENT)) / Math.pow(range, EXPONENT); + this._kernel[i].w = range * sign * Math.abs(o ** EXPONENT) / range ** EXPONENT; } // Calculate the weights: @@ -185,9 +185,9 @@ export class SSSSBlurData { } export class SkinPass extends SettingPass { - name = 'SkinPass' + name = 'SkinPass'; effectName = 'pipeline/ssss-blur'; - outputNames = ['SSSSBlur', 'SSSSBlurDS'] + outputNames = ['SSSSBlur', 'SSSSBlurDS']; ssssBlurData = new SSSSBlurData(); private _activate = false; @@ -220,10 +220,12 @@ export class SkinPass extends SettingPass { this._buildSpecularPass(camera, ppl, inputRT!, inputDS); } - private _buildSSSSBlurPass (camera: Camera, + private _buildSSSSBlurPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): void { + inputDS: string, + ): void { const cameraID = getCameraUniqueID(camera); const pipelineSceneData = ppl.pipelineSceneData; @@ -259,8 +261,12 @@ export class SkinPass extends SettingPass { passIdx = SSSS_BLUR_X_PASS_INDEX; const ssssblurXPassLayoutName = 'ssss-blurX'; const ssssblurXPassPassName = `ssss-blurX${cameraID}`; - this.material.setProperty('blurInfo', new Vec4(camera.fov, skin.blurRadius, - boundingBox, skin.sssIntensity), passIdx); + this.material.setProperty('blurInfo', new Vec4( + camera.fov, + skin.blurRadius, + boundingBox, + skin.sssIntensity, + ), passIdx); this.material.setProperty('kernel', this.ssssBlurData.kernel, passIdx); passContext.updatePassViewPort() .addRenderPass(ssssblurXPassLayoutName, ssssblurXPassPassName) @@ -276,8 +282,12 @@ export class SkinPass extends SettingPass { passIdx = SSSS_BLUR_Y_PASS_INDEX; const ssssblurYPassLayoutName = 'ssss-blurY'; const ssssblurYPassPassName = `ssss-blurY${cameraID}`; - this.material.setProperty('blurInfo', new Vec4(camera.fov, skin.blurRadius, - boundingBox, skin.sssIntensity), passIdx); + this.material.setProperty('blurInfo', new Vec4( + camera.fov, + skin.blurRadius, + boundingBox, + skin.sssIntensity, + ), passIdx); this.material.setProperty('kernel', this.ssssBlurData.kernel, passIdx); passContext.updatePassViewPort() .addRenderPass(ssssblurYPassLayoutName, ssssblurYPassPassName) @@ -290,10 +300,12 @@ export class SkinPass extends SettingPass { .version(); } - private _buildSpecularPass (camera: Camera, + private _buildSpecularPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): void { + inputDS: string, + ): void { const cameraID = getCameraUniqueID(camera); const layoutName = 'specular-pass'; const passName = `specular-pass${cameraID}`; @@ -323,13 +335,19 @@ export class SkinPass extends SettingPass { } pass.addQueue(QueueHint.RENDER_OPAQUE, 'default') - .addSceneOfCamera(camera, new LightInfo(), - SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.PLANAR_SHADOW - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING); + .addSceneOfCamera( + camera, + new LightInfo(), + SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING + | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING, + ); pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'forward-add') - .addSceneOfCamera(camera, new LightInfo(), - SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.PLANAR_SHADOW - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING); + .addSceneOfCamera( + camera, + new LightInfo(), + SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING + | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING, + ); } slotName (camera: Camera, index = 0): string { diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index f2cfd0111b0..6953f8205ca 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -104,7 +104,7 @@ void SceneCulling::collectCullingQueries( } namespace { - +const pipeline::PipelineSceneData* pSceneData = nullptr; bool isNodeVisible(const Node* node, uint32_t visibility) { return node && ((visibility & node->getLayer()) == node->getLayer()); } @@ -113,9 +113,18 @@ uint32_t isModelVisible(const scene::Model& model, uint32_t visibility) { return visibility & static_cast(model.getVisFlags()); } -bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustum) { +bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustum, bool castShadow) { const auto* const modelWorldBounds = model.getWorldBounds(); - return !modelWorldBounds || modelWorldBounds->aabbFrustum(frustum); + if (!modelWorldBounds) { + return true; + } + geometry::AABB transWorldBounds{}; + transWorldBounds.set(modelWorldBounds->getCenter(), modelWorldBounds->getHalfExtents()); + const scene::Shadows& shadows = *pSceneData->getShadows(); + if (shadows.getType() == scene::ShadowType::PLANAR && castShadow) { + modelWorldBounds->transform(shadows.getMatLight(), &transWorldBounds); + } + return transWorldBounds.aabbFrustum(frustum); } void octreeCulling( @@ -183,7 +192,7 @@ void bruteForceCulling( // filter model by view visibility if (isNodeVisible(model.getNode(), visibility) || isModelVisible(model, visibility)) { // frustum culling - if (!isFrustumVisible(model, cameraOrLightFrustum)) { + if (!isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) { continue; } // is skybox, skip @@ -248,14 +257,23 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) models); break; case scene::LightType::DIRECTIONAL: { - const auto& csmLayers = *pplSceneData.getCSMLayers(); + auto& csmLayers = *pplSceneData.getCSMLayers(); const auto* mainLight = dynamic_cast(light); const auto& csmLevel = mainLight->getCSMLevel(); const geometry::Frustum* frustum = nullptr; - if (mainLight->isShadowFixedArea() || csmLevel == scene::CSMLevel::LEVEL_1) { - frustum = &csmLayers.getSpecialLayer()->getValidFrustum(); + const auto& shadows = *pplSceneData.getShadows(); + if (shadows.getType() == scene::ShadowType::PLANAR) { + frustum = &camera.getFrustum(); } else { - frustum = &csmLayers.getLayers()[level]->getValidFrustum(); + if (shadows.isEnabled() && shadows.getType() == scene::ShadowType::SHADOW_MAP && mainLight && mainLight->getNode()) { + csmLayers.update(&pplSceneData, &camera); + } + // const + if (mainLight->isShadowFixedArea() || csmLevel == scene::CSMLevel::LEVEL_1) { + frustum = &csmLayers.getSpecialLayer()->getValidFrustum(); + } else { + frustum = &csmLayers.getLayers()[level]->getValidFrustum(); + } } sceneCulling( skyboxModelToSkip, @@ -281,7 +299,6 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) } namespace { - bool isBlend(const scene::Pass& pass) { bool bBlend = false; for (const auto& target : pass.getBlendState()->targets) { @@ -429,6 +446,7 @@ void SceneCulling::fillRenderQueues( void SceneCulling::buildRenderQueues( const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData) { + pSceneData = &pplSceneData; collectCullingQueries(rg, lg); batchCulling(pplSceneData); fillRenderQueues(rg, pplSceneData); From 132e2b1929e5f063a6a80ffd29ad7892201c04dd Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Tue, 8 Aug 2023 10:48:38 +0800 Subject: [PATCH 04/82] [Optimize] Executor and sceneCulling (#158) * [Optimize] Executor and sceneCulling * Fixed clang tidy action --- cocos/rendering/custom/executor.ts | 163 ++---------------- cocos/rendering/custom/scene-culling.ts | 18 +- .../post-process/passes/skin-pass.ts | 8 +- .../pipeline/custom/NativeExecutor.cpp | 34 +--- .../pipeline/custom/NativeSceneCulling.cpp | 19 +- 5 files changed, 40 insertions(+), 202 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index ed08a405181..445a712e1ed 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -125,7 +125,6 @@ import { PipelineUBO } from '../pipeline-ubo'; import { RenderInfo, RenderObject, WebSceneTask, WebSceneTransversal } from './web-scene'; import { WebSceneVisitor } from './web-scene-visitor'; import { RenderAdditiveLightQueue } from '../render-additive-light-queue'; -import { RenderShadowMapBatchedQueue } from '../render-shadow-map-batched-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; import { @@ -573,37 +572,11 @@ class DeviceRenderQueue { } class SubmitInfo { - public instances = new Set(); - public renderInstanceQueue: InstancedBuffer[] = []; - public opaqueList: RenderInfo[] = []; - public transparentList: RenderInfo[] = []; // - public shadowMap: Map = new Map(); public additiveLight: RenderAdditiveLightQueue | null = null; public reflectionProbe: RenderReflectionProbeQueue | null = null; - private _clearInstances (): void { - const it = this.instances.values(); let res = it.next(); - while (!res.done) { - res.value.clear(); - res = it.next(); - } - this.instances.clear(); - } - - private _clearShadowMap (): void { - for (const shadowMap of this.shadowMap) { - shadowMap[1].clear(); - } - this.shadowMap.clear(); - } - reset (): void { - this._clearInstances(); - this.renderInstanceQueue.length = 0; - this.opaqueList.length = 0; - this.transparentList.length = 0; - this._clearShadowMap(); this.additiveLight = null; this.reflectionProbe = null; } @@ -959,23 +932,7 @@ class DeviceRenderPass { cmdBuff.endRenderPass(); } - private _clear (): void { - for (const [cam, infoMap] of context.submitMap) { - for (const [id, info] of infoMap) { - info.additiveLight?.clear(); - const it = info.instances.values(); let res = it.next(); - while (!res.done) { - res.value.clear(); - res = it.next(); - } - info.renderInstanceQueue = []; - info.instances.clear(); - } - } - } - postPass (): void { - this._clear(); // this.submitMap.clear(); for (const queue of this._deviceQueues) { queue.postRecord(); @@ -1191,70 +1148,7 @@ class DeviceSceneTask extends WebSceneTask { } get graphScene (): GraphScene { return this._graphScene; } public start (): void {} - protected _recordRenderList (isTransparent: boolean): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - const renderList = isTransparent ? currSubmitInfo.transparentList - : currSubmitInfo.opaqueList; - for (let i = 0; i < renderList.length; ++i) { - const { subModel, passIdx } = renderList[i]; - const inputAssembler: InputAssembler = subModel.inputAssembler; - const pass: Pass = subModel.passes[passIdx]; - const shader: Shader = subModel.shaders[passIdx]; - const descriptorSet: DescriptorSet = subModel.descriptorSet; - const pso = PipelineStateManager.getOrCreatePipelineState( - deviceManager.gfxDevice, - pass, - shader, - this._renderPass, - inputAssembler, - ); - this.visitor.bindPipelineState(pso); - this.visitor.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); - this.visitor.bindDescriptorSet(SetIndex.LOCAL, descriptorSet); - this.visitor.bindInputAssembler(inputAssembler); - this.visitor.draw(inputAssembler); - } - } - protected _recordOpaqueList (): void { - this._recordRenderList(false); - } - protected _recordInstences (): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - const it = currSubmitInfo.renderInstanceQueue.length === 0 - ? currSubmitInfo.instances.values() - : currSubmitInfo.renderInstanceQueue.values(); - let res = it.next(); - while (!res.done) { - const { instances, pass, hasPendingModels } = res.value; - if (hasPendingModels) { - this.visitor.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); - let lastPSO: PipelineState | null = null; - for (let b = 0; b < instances.length; ++b) { - const instance = instances[b]; - if (!instance.count) { continue; } - const shader = instance.shader!; - const pso = PipelineStateManager.getOrCreatePipelineState( - deviceManager.gfxDevice, - pass, - shader, - this._renderPass, - instance.ia, - ); - if (lastPSO !== pso) { - this.visitor.bindPipelineState(pso); - lastPSO = pso; - } - const ia: InputAssembler = instance.ia; - this.visitor.bindDescriptorSet(SetIndex.LOCAL, instance.descriptorSet, res.value.dynamicOffsets); - this.visitor.bindInputAssembler(ia); - this.visitor.draw(ia); - } - } - res = it.next(); - } - } + protected _recordUI (): void { const batches = this.camera!.scene!.batches; for (let i = 0; i < batches.length; i++) { @@ -1282,19 +1176,7 @@ class DeviceSceneTask extends WebSceneTask { } } } - protected _recordTransparentList (): void { - this._recordRenderList(true); - } - protected _recordShadowMap (): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.shadowMap.get(this.graphScene.sceneID)!.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } protected _recordReflectionProbe (): void { const submitMap = context.submitMap; const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; @@ -1354,19 +1236,9 @@ class DeviceSceneTask extends WebSceneTask { this.visitor.draw(screenIa); // The desc data obtained from the outside should be cleaned up so that the data can be modified this._clearExtBlitDesc(layoutDesc, extResId); - // if (isEnableEffect()) this.visitor.bindDescriptorSet(SetIndex.GLOBAL, globalDesc); } } - private _recordAdditiveLights (): void { - const devicePass = this._currentQueue.devicePass; - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.additiveLight?.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } + protected _updateGlobal (data: RenderData): void { const devicePass = this._currentQueue.devicePass; updateGlobalDescBinding(data, context.renderGraph.getLayout(devicePass.rasterPassInfo.id)); @@ -1389,11 +1261,9 @@ class DeviceSceneTask extends WebSceneTask { mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet, true); this._currentQueue.isUpdateUBO = true; } - public submit (): void { - const devicePass = this._currentQueue.devicePass; + + private _applyViewport (): void { const queueViewport = this._currentQueue.viewport; - const sceneCulling = context.culling; - this._updateRenderData(); if (queueViewport) { this.visitor.setViewport(queueViewport); this.visitor.setScissor(this._currentQueue.scissor!); @@ -1411,6 +1281,13 @@ class DeviceSceneTask extends WebSceneTask { this.visitor.setViewport(sceneViewport); this.visitor.setScissor(area); } + } + + public submit (): void { + const devicePass = this._currentQueue.devicePass; + const sceneCulling = context.culling; + this._updateRenderData(); + this._applyViewport(); // Currently processing blit and camera first if (this.graphScene.blit) { this._recordBlit(); @@ -1419,26 +1296,14 @@ class DeviceSceneTask extends WebSceneTask { const renderQueueDesc = sceneCulling.sceneQueryIndex.get(this.graphScene.sceneID)!; const renderQueue = sceneCulling.renderQueues[renderQueueDesc.renderQueueTarget]; const graphSceneData = this.graphScene.scene!; - if (graphSceneData.flags & SceneFlags.OPAQUE_OBJECT - || graphSceneData.flags & SceneFlags.CUTOUT_OBJECT) { - renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); - } + renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); - // if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) { - // this._recordAdditiveLights(); - // } - // this.visitor.bindDescriptorSet(SetIndex.GLOBAL, - // context.pipeline.descriptorSet); - if (graphSceneData.flags & SceneFlags.TRANSPARENT_OBJECT) { - // this._recordTransparentList(); - renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); - } + renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); if (graphSceneData.flags & SceneFlags.GEOMETRY) { this.camera!.geometryRenderer?.render( devicePass.renderPass, context.commandBuffer, - context.pipeline.pipelineSceneData, ); } @@ -1701,7 +1566,6 @@ class ExecutorContext { this.width = width; this.height = height; this.additiveLight = new RenderAdditiveLightQueue(pipeline); - this.shadowMapBatched = new RenderShadowMapBatchedQueue(pipeline); this.pools = new ExecutorPools(this); this.blit = new BlitInfo(this); this.culling = new SceneCulling(); @@ -1730,7 +1594,6 @@ class ExecutorContext { readonly root: Root; readonly ubo: PipelineUBO; readonly additiveLight: RenderAdditiveLightQueue; - readonly shadowMapBatched: RenderShadowMapBatchedQueue; readonly submitMap: Map> = new Map>(); readonly pools: ExecutorPools; readonly blit: BlitInfo; diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index f4960124c86..b337a00f6de 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -149,7 +149,6 @@ function addRenderObject ( phaseLayoutId: number, isDrawOpaqueOrMask: boolean, isDrawBlend: boolean, - isDrawShadowCaster: boolean, camera: Camera, model: Model, queue: RenderQueue, @@ -170,15 +169,13 @@ function addRenderObject ( // check scene flags const is_blend = isBlend(pass); const isOpaqueOrMask = !is_blend; - if (!isDrawShadowCaster) { - if (!isDrawBlend && is_blend) { - // skip transparent object - continue; - } - if (!isDrawOpaqueOrMask && isOpaqueOrMask) { - // skip opaque object - continue; - } + if (!isDrawBlend && is_blend) { + // skip transparent object + continue; + } + if (!isDrawOpaqueOrMask && isOpaqueOrMask) { + // skip opaque object + continue; } // add object to queue @@ -407,7 +404,6 @@ export class SceneCulling { phaseLayoutId, isDrawOpaqueOrMask, isDrawBlend, - isDrawShadowCaster, camera, model, renderQueue, diff --git a/cocos/rendering/post-process/passes/skin-pass.ts b/cocos/rendering/post-process/passes/skin-pass.ts index 7da7dbaacff..24bdd068a8b 100644 --- a/cocos/rendering/post-process/passes/skin-pass.ts +++ b/cocos/rendering/post-process/passes/skin-pass.ts @@ -338,15 +338,15 @@ export class SkinPass extends SettingPass { .addSceneOfCamera( camera, new LightInfo(), - SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING, + SceneFlags.TRANSPARENT_OBJECT + | SceneFlags.CUTOUT_OBJECT, ); pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'forward-add') .addSceneOfCamera( camera, new LightInfo(), - SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING, + SceneFlags.TRANSPARENT_OBJECT + | SceneFlags.CUTOUT_OBJECT, ); } diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 5bba3ec861c..c52a13d114c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -1365,32 +1365,14 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { const auto* scene = camera->getScene(); const auto& queueDesc = ctx.context.sceneCulling.sceneQueryIndex.at(sceneID); const auto& queue = ctx.context.sceneCulling.renderQueues[queueDesc.renderQueueTarget]; - bool bDraw = any(sceneData.flags & SceneFlags::DRAW_NON_INSTANCING); - bool bDrawInstancing = any(sceneData.flags & SceneFlags::DRAW_INSTANCING); - if (!bDraw && !bDrawInstancing) { - bDraw = true; - bDrawInstancing = true; - } - const bool bDrawBlend = any(sceneData.flags & SceneFlags::TRANSPARENT_OBJECT); - const bool bDrawOpaqueOrMask = any(sceneData.flags & (SceneFlags::OPAQUE_OBJECT | SceneFlags::CUTOUT_OBJECT)); - const bool bDrawShadowCaster = any(sceneData.flags & SceneFlags::SHADOW_CASTER); - - if (bDrawShadowCaster || bDrawOpaqueOrMask) { - queue.opaqueQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); - if (bDrawInstancing) { - queue.opaqueInstancingQueue.recordCommandBuffer( - ctx.currentPass, ctx.cmdBuff); - } - } - if (bDrawBlend) { - queue.transparentQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); - if (bDrawInstancing) { - queue.transparentInstancingQueue.recordCommandBuffer( - ctx.currentPass, ctx.cmdBuff); - } - } + queue.opaqueQueue.recordCommandBuffer( + ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); + queue.opaqueInstancingQueue.recordCommandBuffer( + ctx.currentPass, ctx.cmdBuff); + queue.transparentQueue.recordCommandBuffer( + ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); + queue.transparentInstancingQueue.recordCommandBuffer( + ctx.currentPass, ctx.cmdBuff); if (any(sceneData.flags & SceneFlags::UI)) { submitUICommands(ctx.currentPass, ctx.currentPassLayoutID, camera, ctx.cmdBuff); diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 6953f8205ca..0b9a2865259 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -324,7 +324,6 @@ void addRenderObject( LayoutGraphData::vertex_descriptor phaseLayoutID, const bool bDrawOpaqueOrMask, const bool bDrawBlend, - const bool bDrawShadowCaster, const scene::Camera& camera, const scene::Model& model, NativeRenderQueue& queue) { @@ -345,15 +344,13 @@ void addRenderObject( // check scene flags const bool bBlend = isBlend(pass); const bool bOpaqueOrMask = !bBlend; - if (!bDrawShadowCaster) { - if (!bDrawBlend && bBlend) { - // skip transparent object - continue; - } - if (!bDrawOpaqueOrMask && bOpaqueOrMask) { - // skip opaque object - continue; - } + if (!bDrawBlend && bBlend) { + // skip transparent object + continue; + } + if (!bDrawOpaqueOrMask && bOpaqueOrMask) { + // skip opaque object + continue; } // add object to queue @@ -434,7 +431,7 @@ void SceneCulling::fillRenderQueues( // fill native queue for (const auto* const model : sourceModels) { addRenderObject( - phaseLayoutID, bDrawOpaqueOrMask, bDrawBlend, bDrawShadowCaster, + phaseLayoutID, bDrawOpaqueOrMask, bDrawBlend, *sceneData.camera, *model, nativeQueue); } From 89b1aa0308c2b3a261bbc113ab3a09f3ea187116 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 8 Aug 2023 11:43:21 +0800 Subject: [PATCH 05/82] fix lint --- native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 7b1b3e22726..5c8ce3ee84f 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -252,7 +252,7 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(queue.swapchain); std::ignore = queue; }, - [&](const FormatView& view) { + [&](const FormatView& view) { // NOLINT(misc-no-recursion) std::ignore = view; auto parentID = parent(vertID, resg); CC_EXPECTS(parentID != resg.null_vertex()); From ace21859e84f92d7616b060af79b2adec8a7c7ee Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Wed, 9 Aug 2023 11:37:57 +0800 Subject: [PATCH 06/82] [Update] mempool logic --- cocos/core/memop/recycle-pool.ts | 28 +++++++++- cocos/rendering/custom/executor.ts | 32 +++-------- cocos/rendering/custom/scene-culling.ts | 59 +++++++++++++++----- cocos/rendering/custom/utils.ts | 30 ++++++++++ cocos/rendering/custom/web-pipeline-types.ts | 49 +++++++++++++--- 5 files changed, 152 insertions(+), 46 deletions(-) diff --git a/cocos/core/memop/recycle-pool.ts b/cocos/core/memop/recycle-pool.ts index ec1aa1a83b7..e23a300eb49 100644 --- a/cocos/core/memop/recycle-pool.ts +++ b/cocos/core/memop/recycle-pool.ts @@ -24,6 +24,11 @@ import { ScalableContainer } from './scalable-container'; +export class UpdateRecyclePool { + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-empty-function + update (...args: any[]) {} +} + /** * @en Recyclable object pool. It's designed to be entirely reused each time. * There is no put and get method, each time you get the [[data]], you can use all elements as new. @@ -36,7 +41,7 @@ import { ScalableContainer } from './scalable-container'; * @see [[Pool]] */ export class RecyclePool extends ScalableContainer { - private _fn: () => T; + private _fn: (...args: any[]) => T; private _dtor: ((obj: T) => void) | null = null; private _count = 0; private _data: T[]; @@ -49,7 +54,7 @@ export class RecyclePool extends ScalableContainer { * @param size Initial pool size * @param dtor The finalizer of element, it's invoked when this container is destroyed or shrunk */ - constructor (fn: () => T, size: number, dtor?: (obj: T) => void) { + constructor (fn: (...args: any[]) => T, size: number, dtor?: (obj: T) => void) { super(); this._fn = fn; this._dtor = dtor || null; @@ -110,6 +115,25 @@ export class RecyclePool extends ScalableContainer { return this._data[this._count++]; } + /** + * @en Create objects with given parameters. If object creation is parameter-based, it is recommended to start with an initial length of 0. + * @zh 通过给定参数构建对象,如果是通过参数构建对象的方式,建议Pool初始长度为0,并让目标类继承UpdateRecyclePool,便于更新操作。 + */ + public addWithArgs (...args: any[]): T { + const data = this._data[this._count]; + if (data) { + this._count++; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + if (data instanceof UpdateRecyclePool) { data.update(...args); } + return data; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + const newObj = this._fn(...args); // 使用传入的参数创建新对象 + this._data[this._count++] = newObj; + + return newObj; + } + /** * @en Destroy the object pool. Please don't use it any more after it is destroyed. * @zh 销毁对象池。销毁后不能继续使用。 diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 445a712e1ed..08371f59de6 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1320,47 +1320,31 @@ class DevicePostSceneTask extends WebSceneTask {} class ExecutorPools { constructor (context: ExecutorContext) { - this.deviceQueuePool = new RecyclePool((): DeviceRenderQueue => new DeviceRenderQueue(), 16); - this.graphScenePool = new RecyclePool((): GraphScene => new GraphScene(), 16); - this.rasterPassInfoPool = new RecyclePool((): RasterPassInfo => new RasterPassInfo(), 16); - this.reflectionProbe = new RecyclePool((): RenderReflectionProbeQueue => new RenderReflectionProbeQueue(context.pipeline), 8); - this.passPool = new RecyclePool((): { priority: number; hash: number; depth: number; shaderId: number; subModel: any; passIdx: number; } => ({ - priority: 0, - hash: 0, - depth: 0, - shaderId: 0, - subModel: null!, - passIdx: 0, - }), 64); - } - addPassInfo (): IRenderPass { - return this.passPool.add(); - } - resetPassInfo (): void { - this.passPool.reset(); + this.deviceQueuePool = new RecyclePool((): DeviceRenderQueue => new DeviceRenderQueue(), 0); + this.graphScenePool = new RecyclePool((): GraphScene => new GraphScene(), 0); + this.rasterPassInfoPool = new RecyclePool((): RasterPassInfo => new RasterPassInfo(), 0); + this.reflectionProbe = new RecyclePool((): RenderReflectionProbeQueue => new RenderReflectionProbeQueue(context.pipeline), 0); } addDeviceQueue (): DeviceRenderQueue { - return this.deviceQueuePool.add(); + return this.deviceQueuePool.addWithArgs(); } addGraphScene (): GraphScene { - return this.graphScenePool.add(); + return this.graphScenePool.addWithArgs(); } addReflectionProbe (): RenderReflectionProbeQueue { - return this.reflectionProbe.add(); + return this.reflectionProbe.addWithArgs(); } addRasterPassInfo (): RasterPassInfo { - return this.rasterPassInfoPool.add(); + return this.rasterPassInfoPool.addWithArgs(); } reset (): void { this.deviceQueuePool.reset(); this.graphScenePool.reset(); this.reflectionProbe.reset(); - this.resetPassInfo(); } readonly deviceQueuePool: RecyclePool; readonly graphScenePool: RecyclePool; readonly reflectionProbe: RecyclePool; - readonly passPool: RecyclePool; readonly rasterPassInfoPool: RecyclePool; } diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index b337a00f6de..91c812521da 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -1,4 +1,4 @@ -import { Vec3, assert } from '../../core'; +import { Vec3, assert, RecyclePool, UpdateRecyclePool } from '../../core'; import { Frustum, intersect, AABB } from '../../core/geometry'; import { CommandBuffer } from '../../gfx'; import { BatchingSchemes, Pass, RenderScene } from '../../render-scene'; @@ -9,8 +9,23 @@ import { hashCombineStr, getSubpassOrPassID, bool } from './define'; import { LayoutGraphData } from './layout-graph'; import { RenderGraph, RenderGraphValue, SceneData } from './render-graph'; import { SceneFlags } from './types'; -import { RenderQueue, RenderQueueDesc } from './web-pipeline-types'; +import { RenderQueue, RenderQueueDesc, instancePool } from './web-pipeline-types'; +import { ObjectPool } from './utils'; +const vec3Pool = new ObjectPool(() => new Vec3()); +const cullingKeyRecycle = new RecyclePool(( + camera: Camera | null, + light: Light | null, + castShadows: boolean, + lightLevel: number, +) => new CullingKey(camera, light, castShadows, lightLevel), 0); +const cullingQueriesRecycle = new RecyclePool(() => new CullingQueries(), 0); +const renderQueueRecycle = new RecyclePool(() => new RenderQueue(), 0); +const renderQueueDescRecycle = new RecyclePool(( + culledSource: number, + renderQueueTarget: number, + lightType: LightType, +) => new RenderQueueDesc(culledSource, renderQueueTarget, lightType), 0); function computeCullingKey (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number): number { let hashCode = 0; if (camera) { @@ -52,12 +67,19 @@ function computeCullingKey (camera: Camera | null, light: Light | null, castShad return hashCode; } -class CullingKey { +class CullingKey extends UpdateRecyclePool { camera: Camera | null; light: Light | null; castShadows = false; lightLevel = 0xffffffff; constructor (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number) { + super(); + this.camera = camera; + this.light = light; + this.castShadows = castShadows; + this.lightLevel = lightLevel; + } + update (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number): void { this.camera = camera; this.light = light; this.castShadows = castShadows; @@ -67,10 +89,14 @@ class CullingKey { let pSceneData: PipelineSceneData; -class CullingQueries { +class CullingQueries extends UpdateRecyclePool { // key: hash val culledResultIndex: Map = new Map(); cullingKeyResult: Map = new Map(); + update (): void { + this.culledResultIndex.clear(); + this.cullingKeyResult.clear(); + } } function isNodeVisible (node: Node, visibility: number): boolean { @@ -138,9 +164,10 @@ function computeSortingDepth (camera: Camera, model: Model): number { let depth = 0; if (model.node) { const node = model.transform; - const tempVec3 = new Vec3(); + const tempVec3 = vec3Pool.acquire(); const position = Vec3.subtract(tempVec3, node.worldPosition, camera.position); depth = position.dot(camera.forward); + vec3Pool.release(tempVec3); } return depth; } @@ -210,15 +237,20 @@ export class SceneCulling { numRenderQueues = 0; layoutGraph; renderGraph; + resetPool (): void { + cullingKeyRecycle.reset(); + cullingQueriesRecycle.reset(); + renderQueueRecycle.reset(); + renderQueueDescRecycle.reset(); + instancePool.reset(); + } clear (): void { + this.resetPool(); this.sceneQueries.clear(); for (const c of this.culledResults) { c.length = 0; } this.culledResults.length = 0; - for (const q of this.renderQueues) { - q.clear(); - } this.renderQueues.length = 0; this.sceneQueryIndex.clear(); this.numCullingQueries = 0; @@ -238,7 +270,7 @@ export class SceneCulling { const scene = sceneData.scene!; let queries = this.sceneQueries.get(scene); if (!queries) { - this.sceneQueries.set(scene, new CullingQueries()); + this.sceneQueries.set(scene, cullingQueriesRecycle.addWithArgs()); queries = this.sceneQueries.get(scene); } const castShadow = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); @@ -253,7 +285,7 @@ export class SceneCulling { this.culledResults.push([]); } queries!.culledResultIndex.set(key, soureceID); - queries!.cullingKeyResult.set(key, new CullingKey(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level)); + queries!.cullingKeyResult.set(key, cullingKeyRecycle.addWithArgs(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level)); return soureceID; } @@ -261,7 +293,7 @@ export class SceneCulling { const targetID = this.numRenderQueues++; if (this.numRenderQueues > this.renderQueues.length) { assert(this.numRenderQueues === (this.renderQueues.length + 1)); - this.renderQueues.push(new RenderQueue()); + this.renderQueues.push(renderQueueRecycle.addWithArgs()); } assert(targetID < this.renderQueues.length); const rq = this.renderQueues[targetID]; @@ -286,7 +318,7 @@ export class SceneCulling { const lightType = sceneData.light.light ? sceneData.light.light.type : LightType.UNKNOWN; // add render queue to query source - this.sceneQueryIndex.set(v, new RenderQueueDesc(sourceID, targetID, lightType)); + this.sceneQueryIndex.set(v, renderQueueDescRecycle.addWithArgs(sourceID, targetID, lightType)); } } @@ -391,9 +423,10 @@ export class SceneCulling { const node = model.node; let depth = 0; if (node) { - const tempVec3 = new Vec3(); + const tempVec3 = vec3Pool.acquire(); Vec3.subtract(tempVec3, node.worldPosition, camera.position); depth = tempVec3.dot(camera.forward); + vec3Pool.release(tempVec3); } renderQueue.opaqueQueue.add(model, depth, 0, 0); } diff --git a/cocos/rendering/custom/utils.ts b/cocos/rendering/custom/utils.ts index 92e985d9731..7654640d022 100644 --- a/cocos/rendering/custom/utils.ts +++ b/cocos/rendering/custom/utils.ts @@ -118,3 +118,33 @@ export function getUBOTypeCount (type: Type): number { return 0; } } + +export class ObjectPool { + // Array to store objects in the pool + private pool: T[] = []; + // Function to create new objects + private createFunction: (...args: U) => T; + + // Constructor, takes a function to create objects as parameter + constructor (createFunction: (...args: U) => T) { + this.createFunction = createFunction; + } + // Get object from the pool, either take from the pool if available or create a new one + acquire (...args: U): T { + if (this.pool.length > 0) { + return this.pool.pop()!; + } + return this.createFunction(...args); + } + // Put the object back into the pool for later reuse + release (obj: T): void { + // Push the object to the end of the pool + if (!this.pool.includes(obj)) { + this.pool.push(obj); + } + } + + create (...args: U): T { + return this.createFunction(...args); + } +} diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index c41128cefd4..753aba5701d 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -1,12 +1,12 @@ +import { RecyclePool, UpdateRecyclePool } from '../../core'; import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; -import { RenderScene } from '../../render-scene'; -import { Camera, Light, LightType, Model, SubModel } from '../../render-scene/scene'; +import { LightType, Model, SubModel } from '../../render-scene/scene'; import { SetIndex } from '../define'; import { InstancedBuffer } from '../instanced-buffer'; import { PipelineStateManager } from '../pipeline-state-manager'; import { SceneFlags } from './types'; -export class DrawInstance { +export class DrawInstance extends UpdateRecyclePool { subModel: SubModel | null; priority: number; hash: number; @@ -22,6 +22,22 @@ export class DrawInstance { shaderID = 0, passIndex = 0, ) { + super(); + this.subModel = subModel; + this.priority = priority; + this.hash = hash; + this.depth = depth; + this.shaderID = shaderID; + this.passIndex = passIndex; + } + update ( + subModel: SubModel | null = null, + priority = 0, + hash = 0, + depth = 0, + shaderID = 0, + passIndex = 0, + ): void { this.subModel = subModel; this.priority = priority; this.hash = hash; @@ -31,6 +47,15 @@ export class DrawInstance { } } +export const instancePool = new RecyclePool(( + subModel: SubModel | null = null, + priority: number = 0, + hash: number = 0, + depth: number = 0, + shaderID: number = 0, + passIndex: number = 0, +) => new DrawInstance(subModel, priority, hash, depth, shaderID, passIndex), 0); + export class RenderDrawQueue { instances: Array = new Array(); @@ -43,7 +68,7 @@ export class RenderDrawQueue { const hash = (0 << 30) | (passPriority as number << 16) | (modelPriority as number << 8) | passIdx; const priority = model.priority; - this.instances.push(new DrawInstance(subModel, priority, hash, depth, shaderId, passIdx)); + this.instances.push(instancePool.addWithArgs(subModel, priority, hash, depth, shaderId, passIdx)); } /** * @en Comparison sorting function. Opaque objects are sorted by priority -> depth front to back -> shader ID. @@ -172,7 +197,7 @@ export class RenderInstancingQueue { } } -export class RenderQueueDesc { +export class RenderQueueDesc extends UpdateRecyclePool { culledSource: number; renderQueueTarget: number; lightType: LightType; @@ -182,13 +207,23 @@ export class RenderQueueDesc { renderQueueTargetIn = 0xFFFFFFFF, lightTypeIn: LightType = LightType.UNKNOWN, ) { + super(); + this.culledSource = culledSourceIn; + this.renderQueueTarget = renderQueueTargetIn; + this.lightType = lightTypeIn; + } + update ( + culledSourceIn = 0xFFFFFFFF, + renderQueueTargetIn = 0xFFFFFFFF, + lightTypeIn: LightType = LightType.UNKNOWN, + ): void { this.culledSource = culledSourceIn; this.renderQueueTarget = renderQueueTargetIn; this.lightType = lightTypeIn; } } -export class RenderQueue { +export class RenderQueue extends UpdateRecyclePool { opaqueQueue: RenderDrawQueue = new RenderDrawQueue(); transparentQueue: RenderDrawQueue = new RenderDrawQueue(); opaqueInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); @@ -212,7 +247,7 @@ export class RenderQueue { instances.clear(); } - clear (): void { + update (): void { this.opaqueQueue.instances.length = 0; this.transparentQueue.instances.length = 0; this._clearInstances(this.opaqueInstancingQueue.batches); From 5c701fcc72bf2ab2604702dae0bb2fd750cd3786 Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Wed, 9 Aug 2023 16:31:39 +0800 Subject: [PATCH 07/82] subresource move (#157) --- .../renderer/frame-graph/ImmutableState.cpp | 8 +- .../cocos/renderer/gfx-base/GFXDef-common.h | 18 +- .../gfx-vulkan/states/VKTextureBarrier.cpp | 8 +- .../pipeline/custom/FGDispatcherTypes.h | 1008 +++++++++-------- .../pipeline/custom/FrameGraphDispatcher.cpp | 438 ++++--- .../pipeline/custom/NativeRenderGraphUtils.h | 12 +- .../pipeline/custom/NativeResourceGraph.cpp | 10 +- .../pipeline/custom/RenderInterfaceTypes.h | 4 +- 8 files changed, 828 insertions(+), 678 deletions(-) diff --git a/native/cocos/renderer/frame-graph/ImmutableState.cpp b/native/cocos/renderer/frame-graph/ImmutableState.cpp index 24a0b9ad604..4c62c3608a3 100644 --- a/native/cocos/renderer/frame-graph/ImmutableState.cpp +++ b/native/cocos/renderer/frame-graph/ImmutableState.cpp @@ -85,10 +85,10 @@ std::pair getBarrier(const ResourceBarrier& ba info.type = barrierInfo.barrierType; info.prevAccesses = getAccessFlags(usage, barrierInfo.beginStatus); info.nextAccesses = getAccessFlags(usage, barrierInfo.endStatus); - info.baseMipLevel = static_cast(barrierInfo.mipRange.base); - info.levelCount = static_cast(barrierInfo.mipRange.len); - info.baseSlice = static_cast(barrierInfo.layerRange.base); - info.sliceCount = static_cast(barrierInfo.layerRange.len); + info.range.mipLevel = static_cast(barrierInfo.mipRange.base); + info.range.levelCount = static_cast(barrierInfo.mipRange.len); + info.range.firstSlice = static_cast(barrierInfo.layerRange.base); + info.range.numSlices = static_cast(barrierInfo.layerRange.len); res.first = gfx::Device::getInstance()->getTextureBarrier(info); res.second = gfxTexture; diff --git a/native/cocos/renderer/gfx-base/GFXDef-common.h b/native/cocos/renderer/gfx-base/GFXDef-common.h index a8a6e4b22d2..da39c2c6dee 100644 --- a/native/cocos/renderer/gfx-base/GFXDef-common.h +++ b/native/cocos/renderer/gfx-base/GFXDef-common.h @@ -1343,6 +1343,18 @@ struct RenderPassInfo { EXPOSE_COPY_FN(RenderPassInfo) }; +struct ResourceRange { + uint32_t width{0}; + uint32_t height{0}; + uint32_t depthOrArraySize{0}; + uint32_t firstSlice{0}; + uint32_t numSlices{0}; + uint32_t mipLevel{0}; + uint32_t levelCount{0}; + uint32_t basePlane{0}; + uint32_t planeCount{0}; +}; + struct ALIGNAS(8) GeneralBarrierInfo { AccessFlags prevAccesses{AccessFlagBit::NONE}; AccessFlags nextAccesses{AccessFlagBit::NONE}; @@ -1360,11 +1372,7 @@ struct ALIGNAS(8) TextureBarrierInfo { BarrierType type{BarrierType::FULL}; - uint32_t baseMipLevel{0}; - uint32_t levelCount{1}; - uint32_t baseSlice{0}; - uint32_t sliceCount{1}; - + ResourceRange range{}; uint64_t discardContents{0}; // @ts-boolean Queue *srcQueue{nullptr}; // @ts-nullable diff --git a/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp b/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp index 86199a46bc0..61aa80a32e2 100644 --- a/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp +++ b/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp @@ -44,10 +44,10 @@ CCVKTextureBarrier::CCVKTextureBarrier(const TextureBarrierInfo &info) : Texture _gpuBarrier->barrier.prevLayout = getAccessLayout(info.prevAccesses); _gpuBarrier->barrier.nextLayout = getAccessLayout(info.nextAccesses); _gpuBarrier->barrier.discardContents = !!info.discardContents; - _gpuBarrier->barrier.subresourceRange.baseMipLevel = 0U; - _gpuBarrier->barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - _gpuBarrier->barrier.subresourceRange.baseArrayLayer = 0U; - _gpuBarrier->barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + _gpuBarrier->barrier.subresourceRange.baseMipLevel = info.range.mipLevel; + _gpuBarrier->barrier.subresourceRange.levelCount = info.range.levelCount; + _gpuBarrier->barrier.subresourceRange.baseArrayLayer = info.range.firstSlice; + _gpuBarrier->barrier.subresourceRange.layerCount = info.range.numSlices; _gpuBarrier->barrier.srcQueueFamilyIndex = info.srcQueue ? static_cast(info.srcQueue)->gpuQueue()->queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED; diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h index 25816eaf81c..577c37bdaec 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h @@ -1,502 +1,506 @@ -/**************************************************************************** - Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. - - http://www.cocos.com - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#pragma once -#include -#include -#include -#include -#include -#include "cocos/base/std/container/string.h" -#include "cocos/base/std/container/vector.h" -#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" -#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/Map.h" -#include "cocos/renderer/pipeline/custom/details/Set.h" -#include "gfx-base/GFXDef-common.h" - -namespace cc { - -namespace render { - -struct NullTag { -}; - -struct ResourceLifeRecord { - uint32_t start{0}; - uint32_t end{0}; -}; - -struct LeafStatus { - bool isExternal{false}; - bool needCulling{false}; -}; - -struct ResourceRange { - uint32_t width{0}; - uint32_t height{0}; - uint32_t depthOrArraySize{0}; - uint32_t firstSlice{0}; - uint32_t numSlices{0}; - uint32_t mipLevel{0}; - uint32_t levelCount{0}; - uint32_t basePlane{0}; - uint32_t planeCount{0}; -}; - -struct AccessStatus { - gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; - ResourceRange range; -}; - -struct ResourceAccessNode { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {resourceStatus.get_allocator().resource()}; - } - - ResourceAccessNode(const allocator_type& alloc) noexcept; // NOLINT - ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc); - ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc); - - ResourceAccessNode(ResourceAccessNode&& rhs) noexcept = default; - ResourceAccessNode(ResourceAccessNode const& rhs) = delete; - ResourceAccessNode& operator=(ResourceAccessNode&& rhs) = default; - ResourceAccessNode& operator=(ResourceAccessNode const& rhs) = default; - - PmrFlatMap resourceStatus; -}; - -struct LayoutAccess { - gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; - gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; -}; - -struct AttachmentInfo { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {parentName.get_allocator().resource()}; - } - - AttachmentInfo(const allocator_type& alloc) noexcept; // NOLINT - AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc); - AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc); - - AttachmentInfo(AttachmentInfo&& rhs) noexcept = default; - AttachmentInfo(AttachmentInfo const& rhs) = delete; - AttachmentInfo& operator=(AttachmentInfo&& rhs) = default; - AttachmentInfo& operator=(AttachmentInfo const& rhs) = default; - - ccstd::pmr::string parentName; - uint32_t attachmentIndex{0}; - uint32_t isResolveView{0}; -}; - -struct FGRenderPassInfo { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {orderedViews.get_allocator().resource()}; - } - - FGRenderPassInfo(const allocator_type& alloc) noexcept; // NOLINT - FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc); - FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc); - - FGRenderPassInfo(FGRenderPassInfo&& rhs) noexcept = default; - FGRenderPassInfo(FGRenderPassInfo const& rhs) = delete; - FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; - FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; - - std::vector colorAccesses; - LayoutAccess dsAccess; - LayoutAccess dsResolveAccess; - gfx::RenderPassInfo rpInfo; - ccstd::pmr::vector orderedViews; - PmrTransparentMap viewIndex; - uint32_t resolveCount{0}; - uint32_t uniqueRasterViewCount{0}; -}; - -struct Barrier { - ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; - gfx::BarrierType type{gfx::BarrierType::FULL}; - gfx::GFXObject* barrier{nullptr}; - RenderGraph::vertex_descriptor beginVert{0xFFFFFFFF}; - RenderGraph::vertex_descriptor endVert{0xFFFFFFFF}; - AccessStatus beginStatus; - AccessStatus endStatus; -}; - -struct BarrierNode { - std::vector frontBarriers; - std::vector rearBarriers; -}; - -struct ResourceAccessGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT - ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - LayoutAccess getAccess(ccstd::pmr::string, RenderGraph::vertex_descriptor vertID); - - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct PassIDTag {}; - struct PassNodeTag {}; - struct RenderPassInfoTag {}; - struct BarrierTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector passID; - ccstd::pmr::vector passResource; - ccstd::pmr::vector rpInfo; - ccstd::pmr::vector barrier; - // UuidGraph - PmrUnorderedMap passIndex; - // Members - ccstd::pmr::vector resourceNames; - PmrUnorderedStringMap resourceIndex; - vertex_descriptor presentPassID{0xFFFFFFFF}; - PmrFlatMap leafPasses; - PmrFlatSet culledPasses; - PmrFlatMap resourceLifeRecord; - ccstd::pmr::vector topologicalOrder; - PmrTransparentMap> resourceAccess; - PmrFlatMap> movedTarget; - PmrFlatMap movedSourceStatus; -}; - -struct RelationGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - RelationGraph(const allocator_type& alloc) noexcept; // NOLINT - RelationGraph(RelationGraph&& rhs) = delete; - RelationGraph(RelationGraph const& rhs) = delete; - RelationGraph& operator=(RelationGraph&& rhs) = delete; - RelationGraph& operator=(RelationGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - RelationGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct DescIDTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector descID; - // UuidGraph - PmrUnorderedMap vertexMap; -}; - -struct RenderingInfo { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {clearColors.get_allocator().resource()}; - } - - RenderingInfo(const allocator_type& alloc) noexcept; // NOLINT - RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc); - RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc); - - RenderingInfo(RenderingInfo&& rhs) noexcept = default; - RenderingInfo(RenderingInfo const& rhs) = delete; - RenderingInfo& operator=(RenderingInfo&& rhs) = default; - RenderingInfo& operator=(RenderingInfo const& rhs) = default; - - gfx::RenderPassInfo renderpassInfo; - gfx::FramebufferInfo framebufferInfo; - ccstd::pmr::vector clearColors; - float clearDepth{0}; - uint8_t clearStencil{0}; -}; - -struct FrameGraphDispatcher { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {resourceAccessGraph.get_allocator().resource()}; - } - - FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; - FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; - - - void enablePassReorder(bool enable); - - // how much paralell-execution weights during pass reorder, - // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. - // 0 by default - void setParalellWeight(float paralellExecWeight); - - void enableMemoryAliasing(bool enable); - - void run(); - - const BarrierNode& getBarrier(RenderGraph::vertex_descriptor u) const; - - const ResourceAccessNode& getAccessNode(RenderGraph::vertex_descriptor u) const; - - const gfx::RenderPassInfo& getRenderPassInfo(RenderGraph::vertex_descriptor u) const; - - RenderingInfo getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph& resg) const; - - LayoutAccess getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const; - - // those resource been moved point to another resID - ResourceGraph::vertex_descriptor realResourceID(const ccstd::pmr::string& name) const; - - PmrFlatMap buildDescriptorIndex( - const PmrTransparentMap>&computeViews, - const PmrTransparentMap& rasterViews, - boost::container::pmr::memory_resource* scratch) const; - - PmrFlatMap buildDescriptorIndex( - const PmrTransparentMap>&computeViews, - boost::container::pmr::memory_resource* scratch) const; - - ResourceAccessGraph resourceAccessGraph; - ResourceGraph& resourceGraph; - const RenderGraph& renderGraph; - const LayoutGraphData& layoutGraph; - boost::container::pmr::memory_resource* scratch{nullptr}; - RelationGraph relationGraph; - bool _enablePassReorder{false}; - bool _enableAutoBarrier{true}; - bool _enableMemoryAliasing{false}; - bool _accessGraphBuilt{false}; - float _paralellExecWeight{0.0F}; -}; - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#pragma once +#include +#include +#include +#include +#include +#include "cocos/base/std/container/string.h" +#include "cocos/base/std/container/vector.h" +#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" +#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/Map.h" +#include "cocos/renderer/pipeline/custom/details/Set.h" +#include "gfx-base/GFXDef-common.h" + +namespace cc { + +namespace render { + +struct NullTag { +}; + +struct ResourceLifeRecord { + uint32_t start{0}; + uint32_t end{0}; +}; + +struct LeafStatus { + bool isExternal{false}; + bool needCulling{false}; +}; + +struct AccessStatus { + gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; + gfx::ResourceRange range; +}; + +struct ResourceAccessNode { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceStatus.get_allocator().resource()}; + } + + ResourceAccessNode(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc); + ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc); + + ResourceAccessNode(ResourceAccessNode&& rhs) noexcept = default; + ResourceAccessNode(ResourceAccessNode const& rhs) = delete; + ResourceAccessNode& operator=(ResourceAccessNode&& rhs) = default; + ResourceAccessNode& operator=(ResourceAccessNode const& rhs) = default; + + PmrFlatMap resourceStatus; +}; + +struct LayoutAccess { + gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; + gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; +}; + +struct AttachmentInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {parentName.get_allocator().resource()}; + } + + AttachmentInfo(const allocator_type& alloc) noexcept; // NOLINT + AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc); + AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc); + + AttachmentInfo(AttachmentInfo&& rhs) noexcept = default; + AttachmentInfo(AttachmentInfo const& rhs) = delete; + AttachmentInfo& operator=(AttachmentInfo&& rhs) = default; + AttachmentInfo& operator=(AttachmentInfo const& rhs) = default; + + ccstd::pmr::string parentName; + uint32_t attachmentIndex{0}; + uint32_t isResolveView{0}; +}; + +struct FGRenderPassInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {orderedViews.get_allocator().resource()}; + } + + FGRenderPassInfo(const allocator_type& alloc) noexcept; // NOLINT + FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc); + FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc); + + FGRenderPassInfo(FGRenderPassInfo&& rhs) noexcept = default; + FGRenderPassInfo(FGRenderPassInfo const& rhs) = delete; + FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; + FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; + + std::vector colorAccesses; + LayoutAccess dsAccess; + LayoutAccess dsResolveAccess; + gfx::RenderPassInfo rpInfo; + ccstd::pmr::vector orderedViews; + PmrTransparentMap viewIndex; + uint32_t resolveCount{0}; + uint32_t uniqueRasterViewCount{0}; +}; + +struct Barrier { + ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; + gfx::BarrierType type{gfx::BarrierType::FULL}; + gfx::GFXObject* barrier{nullptr}; + RenderGraph::vertex_descriptor beginVert{0xFFFFFFFF}; + RenderGraph::vertex_descriptor endVert{0xFFFFFFFF}; + AccessStatus beginStatus; + AccessStatus endStatus; +}; + +struct BarrierNode { + std::vector frontBarriers; + std::vector rearBarriers; +}; + +struct SliceNode { + bool full{false}; + ccstd::pmr::vector mips; +}; + +struct TextureNode { + bool full{false}; + ccstd::pmr::vector slices; +}; + +struct ResourceNode { + bool full{false}; + ccstd::pmr::vector planes; +}; + +struct ResourceAccessGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + LayoutAccess getAccess(ccstd::pmr::string, RenderGraph::vertex_descriptor vertID); + + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct PassIDTag {}; + struct PassNodeTag {}; + struct RenderPassInfoTag {}; + struct BarrierTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector passID; + ccstd::pmr::vector passResource; + ccstd::pmr::vector rpInfo; + ccstd::pmr::vector barrier; + // UuidGraph + PmrUnorderedMap passIndex; + // Members + ccstd::pmr::vector resourceNames; + PmrUnorderedStringMap resourceIndex; + vertex_descriptor presentPassID{0xFFFFFFFF}; + PmrFlatMap leafPasses; + PmrFlatSet culledPasses; + PmrFlatMap resourceLifeRecord; + ccstd::pmr::vector topologicalOrder; + PmrTransparentMap> resourceAccess; + PmrFlatMap> movedTarget; + PmrFlatMap movedSourceStatus; + PmrFlatMap movedTargetStatus; +}; + +struct RelationGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + RelationGraph(const allocator_type& alloc) noexcept; // NOLINT + RelationGraph(RelationGraph&& rhs) = delete; + RelationGraph(RelationGraph const& rhs) = delete; + RelationGraph& operator=(RelationGraph&& rhs) = delete; + RelationGraph& operator=(RelationGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + RelationGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct DescIDTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector descID; + // UuidGraph + PmrUnorderedMap vertexMap; +}; + +struct RenderingInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {clearColors.get_allocator().resource()}; + } + + RenderingInfo(const allocator_type& alloc) noexcept; // NOLINT + RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc); + RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc); + + RenderingInfo(RenderingInfo&& rhs) noexcept = default; + RenderingInfo(RenderingInfo const& rhs) = delete; + RenderingInfo& operator=(RenderingInfo&& rhs) = default; + RenderingInfo& operator=(RenderingInfo const& rhs) = default; + + gfx::RenderPassInfo renderpassInfo; + gfx::FramebufferInfo framebufferInfo; + ccstd::pmr::vector clearColors; + float clearDepth{0}; + uint8_t clearStencil{0}; +}; + +struct FrameGraphDispatcher { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceAccessGraph.get_allocator().resource()}; + } + + FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; + FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; + + + void enablePassReorder(bool enable); + + // how much paralell-execution weights during pass reorder, + // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. + // 0 by default + void setParalellWeight(float paralellExecWeight); + + void enableMemoryAliasing(bool enable); + + void run(); + + const BarrierNode& getBarrier(RenderGraph::vertex_descriptor u) const; + + const ResourceAccessNode& getAccessNode(RenderGraph::vertex_descriptor u) const; + + const gfx::RenderPassInfo& getRenderPassInfo(RenderGraph::vertex_descriptor u) const; + + RenderingInfo getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph& resg) const; + + LayoutAccess getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const; + + // those resource been moved point to another resID + ResourceGraph::vertex_descriptor realResourceID(const ccstd::pmr::string& name) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + const PmrTransparentMap& rasterViews, + boost::container::pmr::memory_resource* scratch) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + boost::container::pmr::memory_resource* scratch) const; + + ResourceAccessGraph resourceAccessGraph; + ResourceGraph& resourceGraph; + const RenderGraph& renderGraph; + const LayoutGraphData& layoutGraph; + boost::container::pmr::memory_resource* scratch{nullptr}; + RelationGraph relationGraph; + bool _enablePassReorder{false}; + bool _enableAutoBarrier{true}; + bool _enableMemoryAliasing{false}; + bool _accessGraphBuilt{false}; + float _paralellExecWeight{0.0F}; +}; + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 6cdd864a2b4..c9913176111 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -122,6 +122,57 @@ ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccst return resourceAccessGraph.resourceIndex.at(name); } +[[nodiscard("concat")]] ccstd::pmr::string concatResName( + std::string_view name0, + std::string_view name1, + boost::container::pmr::memory_resource *scratch) { + ccstd::pmr::string name(name0, scratch); + name += "/"; + name += name1; + return name; +} + +[[nodiscard("subresName")]] ccstd::pmr::string getSubresNameByPlane(const ccstd::pmr::string &resName, + uint32_t planeID, const ResourceGraph &resg, + boost::container::pmr::memory_resource *scratch) { + const auto &desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); + // depth stencil + if (desc.format == gfx::Format::DEPTH_STENCIL) { + auto nameView = planeID == 0 ? DEPTH_PLANE_NAME : STENCIL_PLANE_NAME; + const auto &subresName = concatResName(resName, nameView, scratch); + return subresName; + } + + // array + if (desc.dimension == ResourceDimension::TEXTURE2D && desc.depthOrArraySize > 1) { + ccstd::pmr::set leaves(scratch); + auto resID = vertex(resName, resg); + + using LeafGatherFunc = std::function &)>; + LeafGatherFunc leafGather = [&](ResourceGraph::vertex_descriptor v, const ResourceGraph &resg, ccstd::pmr::set &names) { + for (const auto &e : makeRange(children(v, resg))) { + if (!out_degree(e.target, resg)) { + const auto &rName = get(ResourceGraph::NameTag{}, resg, e.target); + names.emplace(rName); + } else { + leafGather(e.target, resg, names); + } + } + }; + leafGather(resID, resg, leaves); + + auto iter = leaves.begin(); + std::advance(iter, planeID); + return (*iter); + } + + // cube + + // UNREACHABLE + CC_ASSERT(false); + return ""; +} + ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, const ResourceGraph &resg, std::string_view name) { auto resName = get(ResourceGraph::NameTag{}, resg, resID); resName += "/"; @@ -129,15 +180,12 @@ ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor r return findVertex(resName, resg); } -ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, +ResourceGraph::vertex_descriptor locateSubres(const ccstd::pmr::string& originName, const ResourceGraph &resg, - uint32_t basePlane) { - auto ret = resID; - const auto &desc = get(ResourceGraph::DescTag{}, resg, resID); - if (desc.format == gfx::Format::DEPTH_STENCIL) { - ret = basePlane == 0 ? locateSubres(resID, resg, DEPTH_PLANE_NAME) : locateSubres(resID, resg, STENCIL_PLANE_NAME); - } - return ret; + uint32_t basePlane, + boost::container::pmr::memory_resource *scratch) { + const auto &resName = getSubresNameByPlane(originName, basePlane, resg, scratch); + return findVertex(resName, resg); } PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( @@ -152,7 +200,7 @@ PmrFlatMap FrameGraphDispatcher:: const auto &name = computeView.name; CC_EXPECTS(!name.empty()); const auto nameID = layoutGraph.attributeIndex.at(name); - auto subresID = locateSubres(resID, resourceGraph, computeView.plane); + auto subresID = locateSubres(resName, resourceGraph, computeView.plane, scratch); resourceIndex.emplace(nameID, subresID); } } @@ -340,7 +388,7 @@ struct ViewStatus { const AccessType access; const gfx::ShaderStageFlagBit visibility; const gfx::AccessFlags accessFlag; - const ResourceRange ⦥ + const gfx::ResourceRange ⦥ }; constexpr uint32_t EXPECT_START_ID = 0; @@ -423,10 +471,10 @@ bool isResourceView(const ResourceGraph::vertex_descriptor v, const ResourceGrap return resg.isTextureView(v); // || isBufferView } -ResourceRange getResourceRange(const ResourceGraph::vertex_descriptor v, +gfx::ResourceRange getResourceRange(const ResourceGraph::vertex_descriptor v, const ResourceGraph &resg) { const auto &desc = get(ResourceGraph::DescTag{}, resg, v); - ResourceRange range{ + gfx::ResourceRange range{ desc.width, desc.height, desc.depthOrArraySize, @@ -813,16 +861,6 @@ void fillRenderPassInfo(const AttachmentMap &colorMap, } }; -[[nodiscard("concat")]] ccstd::pmr::string concatResName( - std::string_view name0, - std::string_view name1, - boost::container::pmr::memory_resource *scratch) { - ccstd::pmr::string name(name0, scratch); - name += "/"; - name += name1; - return name; -} - void extractNames(const ccstd::pmr::string &resName, const RasterView &view, ccstd::pmr::vector> &names) { @@ -857,26 +895,6 @@ void extractNames(const ccstd::pmr::string &resName, } } -[[nodiscard("subresName")]] ccstd::pmr::string getSubresName(const ccstd::pmr::string &resName, - uint32_t planeID, const ResourceGraph& resg, - boost::container::pmr::memory_resource* scratch) { - const auto& desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); - if(desc.format == gfx::Format::DEPTH_STENCIL) { - auto nameView = planeID == 0 ? DEPTH_PLANE_NAME : STENCIL_PLANE_NAME; - const auto &subresName = concatResName(resName, nameView, scratch); - return subresName; - } - - - // cube - - // array - - // UNREACHABLE - CC_ASSERT(false); - return ""; -} - auto checkRasterViews(const Graphs &graphs, ResourceAccessGraph::vertex_descriptor ragVertID, ResourceAccessNode &node, @@ -965,8 +983,8 @@ bool checkComputeViews(const Graphs &graphs, ResourceAccessGraph::vertex_descrip tryAddEdge(lastVertId, ragVertID, relationGraph); dependent = lastVertId != EXPECT_START_ID; - if(out_degree(resID, resourceGraph)) { - const auto& subresFullName = getSubresName(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); + if (out_degree(resID, resourceGraph) && (computeView.plane != 0xFFFFFFFF)) { + const auto& subresFullName = getSubresNameByPlane(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); } } @@ -1352,118 +1370,163 @@ void startRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); } -namespace { -struct SliceNode { - bool full{false}; - ccstd::pmr::vector mips; -}; - -struct TextureNode { - bool full{false}; - ccstd::pmr::vector slices; -}; - -struct ResourceNode { - ccstd::pmr::vector planes; -}; -} // namespace - -bool rangeCheck(ccstd::pmr::map &status, - const ResourceDesc &desc, - const PmrString &targetName, +bool rangeCheck(ResourceNode &status, + const ResourceDesc &/*desc*/, + const PmrString &/*targetName*/, uint32_t firstSlice, uint32_t numSlices, uint32_t firstMip, uint32_t mipLevels, uint32_t planeIndex) { - if (status.find(targetName) == status.end()) { - status.emplace(targetName, ResourceNode{}); + CC_ASSERT(planeIndex < status.planes.size()); + // spare space in target + bool check = !status.full; + check &= !status.planes[planeIndex].full; + if (check) { + for (auto slice = firstSlice; slice < firstSlice + numSlices; ++slice) { + auto &slices = status.planes[planeIndex].slices; + // no spare space in this slice + check &= !slices[slice].full; + if (!check) { + continue; + } + for (auto mip = firstMip; mip < firstMip + mipLevels; ++mip) { + auto &mips = slices[slice].mips; + // this mip has been taken + check &= mips[mip] == std::numeric_limits::max(); + if (!check) { + continue; + } + mips[mip] = mip; + auto maxIter = std::max_element(mips.begin(), mips.end()); + if ((*maxIter) != std::numeric_limits::max()) { + // linear increasing + check &= (*maxIter) == mips.size() - 1; + slices[slice].full = true; + } + } + if (std::all_of(slices.begin(), slices.end(), [](const SliceNode &sliceNode) { return sliceNode.full; })) { + status.planes[planeIndex].full = true; + } + } } + return check; +} - if (planeIndex >= status[targetName].planes.size()) { - status[targetName].planes.resize(planeIndex + 1); - status[targetName].planes[planeIndex].slices.resize(desc.depthOrArraySize); - for (auto &slice : status[targetName].planes[planeIndex].slices) { - slice.mips.resize(desc.mipLevels, std::numeric_limits::max()); - } +uint32_t getPlaneCount(gfx::Format format) { + switch (format) { + case gfx::Format::DEPTH_STENCIL: + return 2; + default: + return 1; } +} - // no spare space in target - bool check = !status[targetName].planes[planeIndex].full; - for (auto slice = firstSlice; slice < firstSlice + numSlices; ++slice) { - auto &slices = status[targetName].planes[planeIndex].slices; - // no spare space in this slice - check &= !slices[slice].full; - for (auto mip = firstMip; mip < firstMip + mipLevels; ++mip) { - auto &mips = slices[slice].mips; - // this mip has been taken - check &= mips[mip] == std::numeric_limits::max(); - mips[mip] = mip; - auto maxIter = std::max_element(mips.begin(), mips.end()); - if ((*maxIter) != std::numeric_limits::max()) { - // linear increasing - check &= (*maxIter) == mips.size() - 1; - slices[slice].full = true; +bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const ResourceGraph& resourceGraph) { + bool check = true; + ccstd::pmr::vector targets(rag.get_allocator()); + for (const auto &movePair : pass.movePairs) { + const auto &fromResName = movePair.source; + const auto fromResID = resourceGraph.valueIndex.at(fromResName); + const auto &fromResDesc = get(ResourceGraph::DescTag{}, resourceGraph, fromResID); + + const auto &toResName = movePair.target; + const auto toResID = resourceGraph.valueIndex.at(toResName); + const auto &toResDesc = get(ResourceGraph::DescTag{}, resourceGraph, toResID); + + const auto &fromResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, fromResID); + const auto &toResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, toResID); + auto commonUsage = fromResDesc.flags | toResDesc.flags; + + targets.emplace_back(toResName); + + if (rag.movedTargetStatus.find(toResName) == rag.movedTargetStatus.end()) { + rag.movedTargetStatus[toResName].planes.resize(getPlaneCount(toResDesc.format)); + for (auto &plane : rag.movedTargetStatus[toResName].planes) { + plane.slices.resize(toResDesc.depthOrArraySize); + for (auto &slice : plane.slices) { + slice.mips.resize(toResDesc.mipLevels, std::numeric_limits::max()); + } } } - if (std::all_of(slices.begin(), slices.end(), [](const SliceNode &sliceNode) { return sliceNode.full; })) { - status[targetName].planes[planeIndex].full = true; - } + + rangeCheck(rag.movedTargetStatus[toResName], toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); + uint32_t validConditions[] = { + !fromResTraits.hasSideEffects(), + rag.movedSourceStatus.find(toResName) == rag.movedSourceStatus.end(), + rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), + fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, + fromResDesc.dimension == toResDesc.dimension, + fromResDesc.width == toResDesc.width, + fromResDesc.height == toResDesc.height, + fromResDesc.format == toResDesc.format, + fromResDesc.sampleCount == toResDesc.sampleCount, + (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer + }; + bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); + check &= val; } + + // full check + std::for_each(targets.begin(), targets.end(), [&](const ccstd::pmr::string &target) { + ResourceNode &resNode = rag.movedTargetStatus[target]; + resNode.full |= std::all_of(resNode.planes.begin(), resNode.planes.end(), [](const auto &textureNode) { + return textureNode.full; + }); + }); + return check; } -bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const ResourceGraph& resourceGraph) { - bool check = true; - // ccstd::pmr::map sourceCheck; - ccstd::pmr::map targetCheck; - for (const auto &movePair : pass.movePairs) { - const auto &fromResName = movePair.source; - const auto fromResID = resourceGraph.valueIndex.at(fromResName); - const auto &fromResDesc = get(ResourceGraph::DescTag{}, resourceGraph, fromResID); - - const auto &toResName = movePair.target; - const auto toResID = resourceGraph.valueIndex.at(toResName); - const auto &toResDesc = get(ResourceGraph::DescTag{}, resourceGraph, toResID); - - const auto &fromResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, fromResID); - const auto &toResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, toResID); - auto commonUsage = fromResDesc.flags | toResDesc.flags; - - // bool sourceRangeValid = rangeCheck(targetCheck, toResDesc, fromResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); - bool targetRangeValid = rangeCheck(targetCheck, toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); - - uint32_t validConditions[] = { - !fromResTraits.hasSideEffects(), - rag.movedSourceStatus.find(toResName) == rag.movedSourceStatus.end(), - rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), - targetRangeValid, - fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, - fromResDesc.dimension == toResDesc.dimension, - fromResDesc.width == toResDesc.width, - fromResDesc.height == toResDesc.height, - fromResDesc.format == toResDesc.format, - fromResDesc.sampleCount == toResDesc.sampleCount, - (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer - }; - bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); - check &= val; - } - - // full destination - check &= std::all_of(targetCheck.begin(), targetCheck.end(), [](const auto &pair) { - const ResourceNode &resNode = pair.second; - return std::all_of(resNode.planes.begin(), resNode.planes.end(), [](const auto &textureNode) { - return textureNode.full; - }); - }); - - return check; - } +[[nodiscard("subres_name")]] ccstd::pmr::string getSubresourceNameByRange( + const gfx::ResourceRange &range, + boost::container::pmr::memory_resource *scratch) { + ccstd::pmr::string subresName(scratch); + // if () { + // switch (range.firstSlice) { + // case 0: + // return CUBE_RIGHT_NAME.data(); + // case 1: + // return CUBE_LEFT_NAME.data(); + // case 2: + // return CUBE_TOP_NAME.data(); + // case 3: + // return CUBE_BOTTOM_NAME.data(); + // case 4: + // return CUBE_FRONT_NAME.data(); + // case 5: + // return CUBE_REAR_NAME.data(); + // default: + // break; + // } + // } else { + std::string suffix = std::to_string(range.basePlane) + "_" + std::to_string(range.planeCount) + "_" + std::to_string(range.firstSlice) + "_" + std::to_string(range.numSlices) + "_" + std::to_string(range.mipLevel) + "_" + std::to_string(range.levelCount); + subresName = suffix; + // } + return subresName; +} + +gfx::SamplerInfo makePointSamplerInfo() { + return gfx::SamplerInfo{gfx::Filter::POINT, gfx::Filter::POINT, gfx::Filter::POINT}; +} + +SubresourceView makeSubresourceView(const ResourceDesc& desc, const gfx::ResourceRange& range) { + SubresourceView view{}; + view.firstArraySlice = range.firstSlice; + view.numArraySlices = range.numSlices; + view.indexOrFirstMipLevel = range.mipLevel; + view.numMipLevels = range.levelCount; + view.firstPlane = range.basePlane; + view.numPlanes = range.planeCount; + view.format = desc.format; + view.textureView = nullptr; + return view; +} void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) { const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - if(moveValidation(pass, resourceAccessGraph, resourceGraph)) { - for(const auto& pair : pass.movePairs) { + if (moveValidation(pass, resourceAccessGraph, resourceGraph)) { + for (const auto &pair : pass.movePairs) { + auto toleranceRange = getResourceRange(vertex(pair.target, resourceGraph), resourceGraph); auto srcResourceRange = getResourceRange(vertex(pair.source, resourceGraph), resourceGraph); srcResourceRange.firstSlice = pair.targetFirstSlice; srcResourceRange.mipLevel = pair.targetMostDetailedMip; @@ -1471,17 +1534,20 @@ void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) auto lastStatusIter = resourceAccessGraph.resourceAccess.at(pair.source).rbegin(); resourceAccessGraph.movedSourceStatus.emplace(pair.source, AccessStatus{lastStatusIter->second.accessFlag, srcResourceRange}); - resourceAccessGraph.movedTarget[pair.target].emplace_back(pair.source); + resourceAccessGraph.movedTarget[pair.target].emplace(getSubresourceNameByRange(srcResourceRange, resourceAccessGraph.resource()), pair.source); resourceAccessGraph.resourceAccess[pair.target] = resourceAccessGraph.resourceAccess[pair.source]; auto targetResID = findVertex(pair.target, resourceGraph); resourceAccessGraph.resourceIndex[pair.target] = targetResID; auto &rag = resourceAccessGraph; - std::function feedBack = [&](const ccstd::pmr::string &source, ResourceGraph::vertex_descriptor v) { + std::function feedBack = [&]( + const ccstd::pmr::string &source, + ResourceGraph::vertex_descriptor v) { rag.resourceIndex[source] = v; + if (rag.movedTarget.find(source) != rag.movedTarget.end()) { - for (const auto &prt : rag.movedTarget[source]) { + for (const auto &[rangeStr, prt] : rag.movedTarget[source]) { feedBack(prt, v); } } @@ -1548,19 +1614,67 @@ struct DependencyVisitor : boost::dfs_visitor<> { const Graphs &graphs; }; +void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) { + using RecursiveFuncType = std::function &, const ccstd::pmr::string &)>; + RecursiveFuncType addSubres = [&](const PmrFlatMap &subreses, const ccstd::pmr::string &resName) { + if (subreses.size() == 1) { + const auto &src = subreses.begin()->second; + rag.resourceIndex[src] = rag.resourceIndex.at(resName); + + if (rag.movedTarget.find(src) != rag.movedTarget.end()) { + addSubres(rag.movedTarget.at(src), src); + } + } else { + for (const auto &[rangeStr, subres] : subreses) { + auto targetResID = rag.resourceIndex.at(resName); + const auto &targetName = get(ResourceGraph::NameTag{}, resg, targetResID); + const auto &targetDesc = get(ResourceGraph::DescTag{}, resg, targetResID); + const auto &srcResourceRange = rag.movedSourceStatus.at(subres).range; + const auto &targetTraits = get(ResourceGraph::TraitsTag{}, resg, targetResID); + const auto &indexName = concatResName(targetName, subres, rag.resource()); + auto subresID = findVertex(indexName, resg); + if (subresID == ResourceGraph::null_vertex()) { + const auto &subView = makeSubresourceView(targetDesc, srcResourceRange); + // register to resourcegraph + subresID = addVertex( + SubresourceViewTag{}, + std::forward_as_tuple(indexName), + std::forward_as_tuple(targetDesc), + std::forward_as_tuple(targetTraits), + std::forward_as_tuple(), + std::forward_as_tuple(makePointSamplerInfo()), + std::forward_as_tuple(subView), + resg, + targetResID); + } + rag.resourceIndex[subres] = subresID; + + if (rag.movedTarget.find(subres) != rag.movedTarget.end()) { + addSubres(rag.movedTarget.at(subres), subres); + } + } + } + }; + + for (const auto &[targetName, subreses] : rag.movedTarget) { + if (subreses.size() > 1 && rag.movedSourceStatus.find(targetName) == rag.movedSourceStatus.end()) { + addSubres(rag.movedTarget.at(targetName), targetName); + } + } +} + // status of resource access -void buildAccessGraph(const Graphs &graphs) { +void buildAccessGraph(Graphs &graphs) { // what we need: // - pass dependency // - pass attachment access // AccessTable accessRecord; - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; size_t numPasses = 0; numPasses += renderGraph.rasterPasses.size(); numPasses += renderGraph.computePasses.size(); numPasses += renderGraph.copyPasses.size(); - numPasses += renderGraph.movePasses.size(); numPasses += renderGraph.raytracePasses.size(); resourceAccessGraph.reserve(static_cast(numPasses)); @@ -1601,6 +1715,9 @@ void buildAccessGraph(const Graphs &graphs) { } } + // moved resource + subresourceAnalysis(resourceAccessGraph, resourceGraph); + auto &rag = resourceAccessGraph; auto branchCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) -> void { CC_EXPECTS(out_degree(vertex, rag) == 0); @@ -1669,6 +1786,23 @@ void buildAccessGraph(const Graphs &graphs) { } #pragma region BUILD_BARRIERS +gfx::ResourceRange getOriginRange(ResourceGraph::vertex_descriptor v, const gfx::ResourceRange &currRange, const ResourceGraph &resg) { + gfx::ResourceRange ret = currRange; + auto resID = parent(v, resg); + if (resID == ResourceGraph::null_vertex()) { + return ret; + } + + while (resg.isTextureView(resID)) { + const auto &subresView = get(SubresourceViewTag{}, resID, resg); + ret.firstSlice += subresView.firstArraySlice; + ret.mipLevel += subresView.indexOrFirstMipLevel; + ret.basePlane += subresView.firstPlane; + resID = parent(resID, resg); + } + return ret; +} + void buildBarriers(FrameGraphDispatcher &fgDispatcher) { auto *scratch = fgDispatcher.scratch; const auto &renderGraph = fgDispatcher.renderGraph; @@ -1679,7 +1813,7 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { // record resource current in-access and out-access for every single node if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; buildAccessGraph(graphs); fgDispatcher._accessGraphBuilt = true; } @@ -1697,14 +1831,11 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { info.type = barrier.type; gfxBarrier = gfx::Device::getInstance()->getBufferBarrier(info); } else { + const auto& originRange = getOriginRange(barrier.resourceID, barrier.endStatus.range, resourceGraph); gfx::TextureBarrierInfo info; info.prevAccesses = barrier.beginStatus.accessFlag; info.nextAccesses = barrier.endStatus.accessFlag; - const auto &range = barrier.beginStatus.range; - info.baseMipLevel = range.mipLevel; - info.levelCount = range.levelCount; - info.baseSlice = range.firstSlice; - info.sliceCount = range.numSlices; + info.range = originRange; info.type = barrier.type; gfxBarrier = gfx::Device::getInstance()->getTextureBarrier(info); } @@ -1736,7 +1867,8 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { if (holds(dstPassID, renderGraph) || holds(dstPassID, renderGraph)) { const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, dstRagVertID); - if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end()) { + if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end() || + rag.movedTargetStatus.find(resName) != rag.movedTargetStatus.end()) { // renderpass info instead continue; } @@ -2275,7 +2407,7 @@ void passReorder(FrameGraphDispatcher &fgDispatcher) { auto &rag = fgDispatcher.resourceAccessGraph; if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; buildAccessGraph(graphs); fgDispatcher._accessGraphBuilt = true; } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h index bf1ff547408..a28f1c6fdf7 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h @@ -217,12 +217,12 @@ inline bool defaultAttachment(std::string_view slotName) { static constexpr std::string_view DEPTH_PLANE_NAME = "depth"; static constexpr std::string_view STENCIL_PLANE_NAME = "stencil"; -static constexpr std::string_view CUBE_TOP_NAME = "Top"; -static constexpr std::string_view CUBE_BOTTOM_NAME = "Bottom"; -static constexpr std::string_view CUBE_FRONT_NAME = "Front"; -static constexpr std::string_view CUBE_REAR_NAME = "Rear"; -static constexpr std::string_view CUBE_LEFT_NAME = "Left"; -static constexpr std::string_view CUBE_RIGHT_NAME = "Right"; +static constexpr std::string_view CUBE_TOP_NAME = "top"; +static constexpr std::string_view CUBE_BOTTOM_NAME = "bottom"; +static constexpr std::string_view CUBE_FRONT_NAME = "front"; +static constexpr std::string_view CUBE_REAR_NAME = "rear"; +static constexpr std::string_view CUBE_LEFT_NAME = "left"; +static constexpr std::string_view CUBE_RIGHT_NAME = "right"; } // namespace render diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 5c8ce3ee84f..1086f449745 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -262,21 +262,27 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); - mount(device, parentID); // NOLINT(misc-no-recursion) + mount(device, parentID); }, [&](SubresourceView& view) { // NOLINT(misc-no-recursion) + SubresourceView originView = view; auto parentID = parent(vertID, resg); CC_EXPECTS(parentID != resg.null_vertex()); while (resg.isTextureView(parentID)) { + const auto& prtView = get(SubresourceViewTag{}, parentID, resg); + originView.firstPlane += prtView.firstPlane; + originView.firstArraySlice += prtView.firstArraySlice; + originView.indexOrFirstMipLevel += prtView.indexOrFirstMipLevel; parentID = parent(parentID, resg); } CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); + mount(device, parentID); // NOLINT(misc-no-recursion) auto* parentTexture = resg.getTexture(parentID); const auto& desc = get(ResourceGraph::DescTag{}, resg, vertID); if (!view.textureView) { - auto textureViewInfo = getTextureViewInfo(view, desc); + auto textureViewInfo = getTextureViewInfo(originView, desc); textureViewInfo.texture = parentTexture; view.textureView = device->createTexture(textureViewInfo); } diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 4c5e015b567..f6339a3fa76 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -638,10 +638,10 @@ class BasicRenderPassBuilder : public Setter { addDepthStencil(name, loadOp, storeOp, depth, stencil, gfx::ClearFlagBit::DEPTH_STENCIL); } void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0); + addTexture(name, slotName, nullptr, 0xFFFFFFFF); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0); + addTexture(name, slotName, sampler, 0xFFFFFFFF); } RenderQueueBuilder *addQueue() { return addQueue(QueueHint::NONE, "default"); From 003f4f9ad5b148586ffb46ccd3141032c140bebb Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 9 Aug 2023 16:43:15 +0800 Subject: [PATCH 08/82] add constants --- cocos/rendering/custom/pipeline.ts | 13 +- cocos/rendering/custom/types.ts | 6 +- cocos/rendering/custom/web-pipeline.ts | 29 +++- .../pipeline/custom/NativePipelineTypes.h | 127 +++++++++++++++++- .../pipeline/custom/NativeRenderGraph.cpp | 2 +- .../renderer/pipeline/custom/NativeSetter.cpp | 15 +++ .../pipeline/custom/RenderCommonJsb.cpp | 7 + .../custom/RenderCommonSerialization.h | 2 + .../pipeline/custom/RenderCommonTypes.h | 5 + .../pipeline/custom/RenderInterfaceTypes.h | 13 +- 10 files changed, 207 insertions(+), 12 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index c679c5796dd..68e6d54d984 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -37,9 +37,12 @@ import { GlobalDSManager } from '../global-descriptor-set-manager'; import { Mat4, Quat, Vec2, Vec4 } from '../../core/math'; import { MacroRecord } from '../../render-scene/core/pass-utils'; 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 { RenderWindow } from '../../render-scene/core/render-window'; import { Light, Model } from '../../render-scene/scene'; +import { SphereLight } from '../../render-scene/scene/sphere-light'; import { SpotLight } from '../../render-scene/scene/spot-light'; /** @@ -377,6 +380,11 @@ export interface Setter extends RenderNode { setSampler (name: string, sampler: Sampler): void; setBuiltinCameraConstants (camera: Camera): void; setBuiltinShadowMapConstants (light: DirectionalLight): void; + setBuiltinDirectionalLightConstants (light: DirectionalLight, camera: Camera): void; + setBuiltinSphereLightConstants (light: SphereLight, camera: Camera): void; + setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void; + setBuiltinPointLightConstants (light: PointLight, camera: Camera): void; + setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void; setBuiltinDirectionalLightViewConstants (light: DirectionalLight, level?: number): void; setBuiltinSpotLightViewConstants (light: SpotLight): void; } @@ -402,7 +410,10 @@ export interface RenderQueueBuilder extends Setter { camera: Camera, light: LightInfo, sceneFlags?: SceneFlags): void; - addScene (camera: Camera, sceneFlags: SceneFlags): void; + addScene ( + camera: Camera, + sceneFlags: SceneFlags, + light?: Light | null): void; addSceneCulledByDirectionalLight ( camera: Camera, sceneFlags: SceneFlags, diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index d09e3b8a9fe..bde9ca132f7 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -288,12 +288,14 @@ export function getClearValueTypeName (e: ClearValueType): string { } export class LightInfo { - constructor (light: Light | null = null, level = 0) { + constructor (light: Light | null = null, level = 0, culledByLight = false) { this.light = light; this.level = level; + this.culledByLight = culledByLight; } /*refcount*/ light: Light | null; level: number; + culledByLight: boolean; } export enum DescriptorTypeOrder { @@ -505,11 +507,13 @@ export class PipelineStatistics { export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { // skip, v.light: Light ar.writeNumber(v.level); + ar.writeBool(v.culledByLight); } export function loadLightInfo (ar: InputArchive, v: LightInfo): void { // skip, v.light: Light v.level = ar.readNumber(); + v.culledByLight = ar.readBool(); } export function saveDescriptor (ar: OutputArchive, v: Descriptor): void { diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 08e171ab45c..7cf6e6653a1 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -31,7 +31,7 @@ import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; -import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows } from '../../render-scene/scene'; +import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; import { DescriptorSetData, DescriptorSetLayoutData, LayoutGraphData } from './layout-graph'; import { Executor } from './executor'; @@ -255,16 +255,31 @@ export class WebSetter { this._data.samplers.set(num, sampler); } public setBuiltinCameraConstants (camera: Camera): void { - + // TODO } public setBuiltinShadowMapConstants (light: Light, numLevels?: number): void { - + // TODO } public setBuiltinDirectionalLightViewConstants (light: DirectionalLight): void { - + // TODO } public setBuiltinSpotLightViewConstants (light: SpotLight): void { - + // TODO + } + public setBuiltinDirectionalLightConstants (light: DirectionalLight, camera: Camera): void { + // TODO + } + public setBuiltinSphereLightConstants (light: SphereLight, camera: Camera): void { + // TODO + } + public setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void { + // TODO + } + public setBuiltinPointLightConstants (light: PointLight, camera: Camera): void { + // TODO + } + public setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void { + // TODO } public hasSampler (name: string): boolean { const id = this._lg.attributeIndex.get(name); @@ -1084,7 +1099,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR this._pass.rasterViews.set(name, view); } resolveRenderTarget (source: string, target: string): void { - + // TODO } resolveDepthStencil ( source: string, @@ -1092,7 +1107,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR depthMode?: ResolveMode, stencilMode?: ResolveMode, ): void { - + // TODO } private _addComputeResource (name: string, accessType: AccessType, slotName: string): void { const view = new ComputeView(slotName); diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index b21235bc46b..1fdb0ebed7d 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -88,6 +88,11 @@ class NativeSetter : public NativeRenderNode { void setSampler(const ccstd::string &name, gfx::Sampler *sampler) /*implements*/; void setBuiltinCameraConstants(const scene::Camera *camera) /*implements*/; void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) /*implements*/; + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) /*implements*/; void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) /*implements*/; void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) /*implements*/; @@ -175,6 +180,21 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -183,7 +203,7 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS } void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) override; - void addScene(const scene::Camera *camera, SceneFlags sceneFlags) override; + void addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) override; void addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) override; void addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) override; void addFullscreenQuad(Material *material, uint32_t passID, SceneFlags sceneFlags) override; @@ -250,6 +270,21 @@ class NativeRenderSubpassBuilder final : public RenderSubpassBuilder, public Nat void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -346,6 +381,21 @@ class NativeMultisampleRenderSubpassBuilder final : public MultisampleRenderSubp void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -445,6 +495,21 @@ class NativeComputeSubpassBuilder final : public ComputeSubpassBuilder, public N void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -517,6 +582,21 @@ class NativeRenderPassBuilder final : public RenderPassBuilder, public NativeSet void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -601,6 +681,21 @@ class NativeMultisampleRenderPassBuilder final : public MultisampleRenderPassBui void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -684,6 +779,21 @@ class NativeComputeQueueBuilder final : public ComputeQueueBuilder, public Nativ void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -751,6 +861,21 @@ class NativeComputePassBuilder final : public ComputePassBuilder, public NativeS void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 91c9dcf73b4..0ec4a9aa3a2 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -736,7 +736,7 @@ void NativeRenderQueueBuilder::addSceneOfCamera( data); } -void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags) { +void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{}); auto sceneID = addVertex2( diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index 6f4e2ca6fd9..bb313d6cfca 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -148,6 +148,21 @@ void NativeSetter::setBuiltinShadowMapConstants( setShadowUBOView(*device, *layoutGraph, sceneData, *light, data); } +void NativeSetter::setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) { +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp index 9bb23563b0b..c7fed6ceedb 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp @@ -44,6 +44,9 @@ bool nativevalue_to_se(const cc::render::LightInfo &from, se::Value &to, se::Obj nativevalue_to_se(from.level, tmp, ctx); obj->setProperty("level", tmp); + nativevalue_to_se(from.culledByLight, tmp, ctx); + obj->setProperty("culledByLight", tmp); + to.setObject(obj); return true; } @@ -242,6 +245,10 @@ bool sevalue_to_native(const se::Value &from, cc::render: if(!field.isNullOrUndefined()) { ok &= sevalue_to_native(field, &(to->level), ctx); } + obj->getProperty("culledByLight", &field, true); + if(!field.isNullOrUndefined()) { + ok &= sevalue_to_native(field, &(to->culledByLight), ctx); + } return ok; } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h index 49fa456c4cd..4c9467badf2 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h @@ -40,11 +40,13 @@ namespace render { inline void save(OutputArchive& ar, const LightInfo& v) { // skip, light: IntrusivePtr save(ar, v.level); + save(ar, v.culledByLight); } inline void load(InputArchive& ar, LightInfo& v) { // skip, light: IntrusivePtr load(ar, v.level); + load(ar, v.culledByLight); } inline void save(OutputArchive& ar, const Descriptor& v) { diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index eb6dfe6a9b3..cad5d71c02c 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -211,12 +211,17 @@ enum class ClearValueType { struct LightInfo { LightInfo() = default; + LightInfo(IntrusivePtr lightIn, uint32_t levelIn, bool culledByLightIn) noexcept + : light(std::move(lightIn)), + level(levelIn), + culledByLight(culledByLightIn) {} LightInfo(IntrusivePtr lightIn, uint32_t levelIn) noexcept : light(std::move(lightIn)), level(levelIn) {} IntrusivePtr light; uint32_t level{0}; + bool culledByLight{false}; }; enum class DescriptorTypeOrder { diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index f6339a3fa76..476d09c6f48 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -57,7 +57,10 @@ class GeometryRenderer; namespace scene { class DirectionalLight; +class SphereLight; class SpotLight; +class PointLight; +class RangedDirectionalLight; class Model; class RenderScene; class RenderWindow; @@ -452,6 +455,11 @@ class Setter : public RenderNode { virtual void setSampler(const ccstd::string &name, gfx::Sampler *sampler) = 0; virtual void setBuiltinCameraConstants(const scene::Camera *camera) = 0; virtual void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) = 0; + virtual void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) = 0; virtual void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) = 0; virtual void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) = 0; void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light) { @@ -480,7 +488,7 @@ class RenderQueueBuilder : public Setter { * @param sceneFlags @en Rendering flags of the scene @zh 场景渲染标志位 */ virtual void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) = 0; - virtual void addScene(const scene::Camera *camera, SceneFlags sceneFlags) = 0; + virtual void addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) = 0; virtual void addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) = 0; virtual void addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) = 0; /** @@ -520,6 +528,9 @@ class RenderQueueBuilder : public Setter { void addSceneOfCamera(scene::Camera *camera, LightInfo light) { addSceneOfCamera(camera, std::move(light), SceneFlags::NONE); } + void addScene(const scene::Camera *camera, SceneFlags sceneFlags) { + addScene(camera, sceneFlags, nullptr); + } void addFullscreenQuad(Material *material, uint32_t passID) { addFullscreenQuad(material, passID, SceneFlags::NONE); } From a31e5a9f509b2a53ada55ad2e5882316f22e661d Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 9 Aug 2023 17:18:23 +0800 Subject: [PATCH 09/82] fix lint --- cocos/rendering/custom/web-pipeline.ts | 12 +++++++++--- .../renderer/pipeline/custom/NativeRenderGraph.cpp | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 7cf6e6653a1..fa46e3dab45 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -237,7 +237,9 @@ export class WebSetter { public offsetFloat (v: number, offset: number): void { this._copyToBuffer(v, offset, Type.FLOAT); } - public setBuffer (name: string, buffer: Buffer): void {} + public setBuffer (name: string, buffer: Buffer): void { + // TODO + } public setTexture (name: string, texture: Texture): void { if (this._getCurrDescriptorBlock(name) === -1) { return; @@ -245,8 +247,12 @@ export class WebSetter { const num = this._lg.attributeIndex.get(name)!; this._data.textures.set(num, texture); } - public setReadWriteBuffer (name: string, buffer: Buffer): void {} - public setReadWriteTexture (name: string, texture: Texture): void {} + public setReadWriteBuffer (name: string, buffer: Buffer): void { + // TODO + } + public setReadWriteTexture (name: string, texture: Texture): void { + // TODO + } public setSampler (name: string, sampler: Sampler): void { if (this._getCurrDescriptorBlock(name) === -1) { return; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 0ec4a9aa3a2..960cb08d0d4 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -737,6 +737,7 @@ void NativeRenderQueueBuilder::addSceneOfCamera( } void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { + std::ignore = light; SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{}); auto sceneID = addVertex2( From 8f676b695eb3d5a1b12265f9cda76b119e827700 Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Wed, 9 Aug 2023 17:48:01 +0800 Subject: [PATCH 10/82] type update (#160) --- .../pipeline/custom/FGDispatcherTypes.cpp | 3 +- .../pipeline/custom/FGDispatcherTypes.h | 1012 ++++++++--------- 2 files changed, 508 insertions(+), 507 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp index 1982760fd0a..41d24898bcf 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp @@ -95,7 +95,8 @@ ResourceAccessGraph::ResourceAccessGraph(const allocator_type& alloc) noexcept topologicalOrder(alloc), resourceAccess(alloc), movedTarget(alloc), - movedSourceStatus(alloc) {} + movedSourceStatus(alloc), + movedTargetStatus(alloc) {} // ContinuousContainer void ResourceAccessGraph::reserve(vertices_size_type sz) { diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h index 577c37bdaec..369d9460a0f 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h @@ -1,506 +1,506 @@ -/**************************************************************************** - Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. - - http://www.cocos.com - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#pragma once -#include -#include -#include -#include -#include -#include "cocos/base/std/container/string.h" -#include "cocos/base/std/container/vector.h" -#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" -#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/Map.h" -#include "cocos/renderer/pipeline/custom/details/Set.h" -#include "gfx-base/GFXDef-common.h" - -namespace cc { - -namespace render { - -struct NullTag { -}; - -struct ResourceLifeRecord { - uint32_t start{0}; - uint32_t end{0}; -}; - -struct LeafStatus { - bool isExternal{false}; - bool needCulling{false}; -}; - -struct AccessStatus { - gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; - gfx::ResourceRange range; -}; - -struct ResourceAccessNode { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {resourceStatus.get_allocator().resource()}; - } - - ResourceAccessNode(const allocator_type& alloc) noexcept; // NOLINT - ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc); - ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc); - - ResourceAccessNode(ResourceAccessNode&& rhs) noexcept = default; - ResourceAccessNode(ResourceAccessNode const& rhs) = delete; - ResourceAccessNode& operator=(ResourceAccessNode&& rhs) = default; - ResourceAccessNode& operator=(ResourceAccessNode const& rhs) = default; - - PmrFlatMap resourceStatus; -}; - -struct LayoutAccess { - gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; - gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; -}; - -struct AttachmentInfo { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {parentName.get_allocator().resource()}; - } - - AttachmentInfo(const allocator_type& alloc) noexcept; // NOLINT - AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc); - AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc); - - AttachmentInfo(AttachmentInfo&& rhs) noexcept = default; - AttachmentInfo(AttachmentInfo const& rhs) = delete; - AttachmentInfo& operator=(AttachmentInfo&& rhs) = default; - AttachmentInfo& operator=(AttachmentInfo const& rhs) = default; - - ccstd::pmr::string parentName; - uint32_t attachmentIndex{0}; - uint32_t isResolveView{0}; -}; - -struct FGRenderPassInfo { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {orderedViews.get_allocator().resource()}; - } - - FGRenderPassInfo(const allocator_type& alloc) noexcept; // NOLINT - FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc); - FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc); - - FGRenderPassInfo(FGRenderPassInfo&& rhs) noexcept = default; - FGRenderPassInfo(FGRenderPassInfo const& rhs) = delete; - FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; - FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; - - std::vector colorAccesses; - LayoutAccess dsAccess; - LayoutAccess dsResolveAccess; - gfx::RenderPassInfo rpInfo; - ccstd::pmr::vector orderedViews; - PmrTransparentMap viewIndex; - uint32_t resolveCount{0}; - uint32_t uniqueRasterViewCount{0}; -}; - -struct Barrier { - ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; - gfx::BarrierType type{gfx::BarrierType::FULL}; - gfx::GFXObject* barrier{nullptr}; - RenderGraph::vertex_descriptor beginVert{0xFFFFFFFF}; - RenderGraph::vertex_descriptor endVert{0xFFFFFFFF}; - AccessStatus beginStatus; - AccessStatus endStatus; -}; - -struct BarrierNode { - std::vector frontBarriers; - std::vector rearBarriers; -}; - -struct SliceNode { - bool full{false}; - ccstd::pmr::vector mips; -}; - -struct TextureNode { - bool full{false}; - ccstd::pmr::vector slices; -}; - -struct ResourceNode { - bool full{false}; - ccstd::pmr::vector planes; -}; - -struct ResourceAccessGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT - ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - LayoutAccess getAccess(ccstd::pmr::string, RenderGraph::vertex_descriptor vertID); - - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct PassIDTag {}; - struct PassNodeTag {}; - struct RenderPassInfoTag {}; - struct BarrierTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector passID; - ccstd::pmr::vector passResource; - ccstd::pmr::vector rpInfo; - ccstd::pmr::vector barrier; - // UuidGraph - PmrUnorderedMap passIndex; - // Members - ccstd::pmr::vector resourceNames; - PmrUnorderedStringMap resourceIndex; - vertex_descriptor presentPassID{0xFFFFFFFF}; - PmrFlatMap leafPasses; - PmrFlatSet culledPasses; - PmrFlatMap resourceLifeRecord; - ccstd::pmr::vector topologicalOrder; - PmrTransparentMap> resourceAccess; - PmrFlatMap> movedTarget; - PmrFlatMap movedSourceStatus; - PmrFlatMap movedTargetStatus; -}; - -struct RelationGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - RelationGraph(const allocator_type& alloc) noexcept; // NOLINT - RelationGraph(RelationGraph&& rhs) = delete; - RelationGraph(RelationGraph const& rhs) = delete; - RelationGraph& operator=(RelationGraph&& rhs) = delete; - RelationGraph& operator=(RelationGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - RelationGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct DescIDTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector descID; - // UuidGraph - PmrUnorderedMap vertexMap; -}; - -struct RenderingInfo { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {clearColors.get_allocator().resource()}; - } - - RenderingInfo(const allocator_type& alloc) noexcept; // NOLINT - RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc); - RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc); - - RenderingInfo(RenderingInfo&& rhs) noexcept = default; - RenderingInfo(RenderingInfo const& rhs) = delete; - RenderingInfo& operator=(RenderingInfo&& rhs) = default; - RenderingInfo& operator=(RenderingInfo const& rhs) = default; - - gfx::RenderPassInfo renderpassInfo; - gfx::FramebufferInfo framebufferInfo; - ccstd::pmr::vector clearColors; - float clearDepth{0}; - uint8_t clearStencil{0}; -}; - -struct FrameGraphDispatcher { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {resourceAccessGraph.get_allocator().resource()}; - } - - FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; - FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; - - - void enablePassReorder(bool enable); - - // how much paralell-execution weights during pass reorder, - // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. - // 0 by default - void setParalellWeight(float paralellExecWeight); - - void enableMemoryAliasing(bool enable); - - void run(); - - const BarrierNode& getBarrier(RenderGraph::vertex_descriptor u) const; - - const ResourceAccessNode& getAccessNode(RenderGraph::vertex_descriptor u) const; - - const gfx::RenderPassInfo& getRenderPassInfo(RenderGraph::vertex_descriptor u) const; - - RenderingInfo getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph& resg) const; - - LayoutAccess getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const; - - // those resource been moved point to another resID - ResourceGraph::vertex_descriptor realResourceID(const ccstd::pmr::string& name) const; - - PmrFlatMap buildDescriptorIndex( - const PmrTransparentMap>&computeViews, - const PmrTransparentMap& rasterViews, - boost::container::pmr::memory_resource* scratch) const; - - PmrFlatMap buildDescriptorIndex( - const PmrTransparentMap>&computeViews, - boost::container::pmr::memory_resource* scratch) const; - - ResourceAccessGraph resourceAccessGraph; - ResourceGraph& resourceGraph; - const RenderGraph& renderGraph; - const LayoutGraphData& layoutGraph; - boost::container::pmr::memory_resource* scratch{nullptr}; - RelationGraph relationGraph; - bool _enablePassReorder{false}; - bool _enableAutoBarrier{true}; - bool _enableMemoryAliasing{false}; - bool _accessGraphBuilt{false}; - float _paralellExecWeight{0.0F}; -}; - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#pragma once +#include +#include +#include +#include +#include +#include "cocos/base/std/container/string.h" +#include "cocos/base/std/container/vector.h" +#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" +#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/Map.h" +#include "cocos/renderer/pipeline/custom/details/Set.h" +#include "gfx-base/GFXDef-common.h" + +namespace cc { + +namespace render { + +struct NullTag { +}; + +struct ResourceLifeRecord { + uint32_t start{0}; + uint32_t end{0}; +}; + +struct LeafStatus { + bool isExternal{false}; + bool needCulling{false}; +}; + +struct AccessStatus { + gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; + gfx::ResourceRange range; +}; + +struct ResourceAccessNode { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceStatus.get_allocator().resource()}; + } + + ResourceAccessNode(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc); + ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc); + + ResourceAccessNode(ResourceAccessNode&& rhs) noexcept = default; + ResourceAccessNode(ResourceAccessNode const& rhs) = delete; + ResourceAccessNode& operator=(ResourceAccessNode&& rhs) = default; + ResourceAccessNode& operator=(ResourceAccessNode const& rhs) = default; + + PmrFlatMap resourceStatus; +}; + +struct LayoutAccess { + gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; + gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; +}; + +struct AttachmentInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {parentName.get_allocator().resource()}; + } + + AttachmentInfo(const allocator_type& alloc) noexcept; // NOLINT + AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc); + AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc); + + AttachmentInfo(AttachmentInfo&& rhs) noexcept = default; + AttachmentInfo(AttachmentInfo const& rhs) = delete; + AttachmentInfo& operator=(AttachmentInfo&& rhs) = default; + AttachmentInfo& operator=(AttachmentInfo const& rhs) = default; + + ccstd::pmr::string parentName; + uint32_t attachmentIndex{0}; + uint32_t isResolveView{0}; +}; + +struct FGRenderPassInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {orderedViews.get_allocator().resource()}; + } + + FGRenderPassInfo(const allocator_type& alloc) noexcept; // NOLINT + FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc); + FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc); + + FGRenderPassInfo(FGRenderPassInfo&& rhs) noexcept = default; + FGRenderPassInfo(FGRenderPassInfo const& rhs) = delete; + FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; + FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; + + std::vector colorAccesses; + LayoutAccess dsAccess; + LayoutAccess dsResolveAccess; + gfx::RenderPassInfo rpInfo; + ccstd::pmr::vector orderedViews; + PmrTransparentMap viewIndex; + uint32_t resolveCount{0}; + uint32_t uniqueRasterViewCount{0}; +}; + +struct Barrier { + ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; + gfx::BarrierType type{gfx::BarrierType::FULL}; + gfx::GFXObject* barrier{nullptr}; + RenderGraph::vertex_descriptor beginVert{0xFFFFFFFF}; + RenderGraph::vertex_descriptor endVert{0xFFFFFFFF}; + AccessStatus beginStatus; + AccessStatus endStatus; +}; + +struct BarrierNode { + std::vector frontBarriers; + std::vector rearBarriers; +}; + +struct SliceNode { + bool full{false}; + std::vector mips; +}; + +struct TextureNode { + bool full{false}; + std::vector slices; +}; + +struct ResourceNode { + bool full{false}; + std::vector planes; +}; + +struct ResourceAccessGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + LayoutAccess getAccess(ccstd::pmr::string, RenderGraph::vertex_descriptor vertID); + + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct PassIDTag {}; + struct PassNodeTag {}; + struct RenderPassInfoTag {}; + struct BarrierTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector passID; + ccstd::pmr::vector passResource; + ccstd::pmr::vector rpInfo; + ccstd::pmr::vector barrier; + // UuidGraph + PmrUnorderedMap passIndex; + // Members + ccstd::pmr::vector resourceNames; + PmrUnorderedStringMap resourceIndex; + vertex_descriptor presentPassID{0xFFFFFFFF}; + PmrFlatMap leafPasses; + PmrFlatSet culledPasses; + PmrFlatMap resourceLifeRecord; + ccstd::pmr::vector topologicalOrder; + PmrTransparentMap> resourceAccess; + PmrFlatMap> movedTarget; + PmrFlatMap movedSourceStatus; + PmrFlatMap movedTargetStatus; +}; + +struct RelationGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + RelationGraph(const allocator_type& alloc) noexcept; // NOLINT + RelationGraph(RelationGraph&& rhs) = delete; + RelationGraph(RelationGraph const& rhs) = delete; + RelationGraph& operator=(RelationGraph&& rhs) = delete; + RelationGraph& operator=(RelationGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + RelationGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct DescIDTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector descID; + // UuidGraph + PmrUnorderedMap vertexMap; +}; + +struct RenderingInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {clearColors.get_allocator().resource()}; + } + + RenderingInfo(const allocator_type& alloc) noexcept; // NOLINT + RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc); + RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc); + + RenderingInfo(RenderingInfo&& rhs) noexcept = default; + RenderingInfo(RenderingInfo const& rhs) = delete; + RenderingInfo& operator=(RenderingInfo&& rhs) = default; + RenderingInfo& operator=(RenderingInfo const& rhs) = default; + + gfx::RenderPassInfo renderpassInfo; + gfx::FramebufferInfo framebufferInfo; + ccstd::pmr::vector clearColors; + float clearDepth{0}; + uint8_t clearStencil{0}; +}; + +struct FrameGraphDispatcher { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceAccessGraph.get_allocator().resource()}; + } + + FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; + FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; + + + void enablePassReorder(bool enable); + + // how much paralell-execution weights during pass reorder, + // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. + // 0 by default + void setParalellWeight(float paralellExecWeight); + + void enableMemoryAliasing(bool enable); + + void run(); + + const BarrierNode& getBarrier(RenderGraph::vertex_descriptor u) const; + + const ResourceAccessNode& getAccessNode(RenderGraph::vertex_descriptor u) const; + + const gfx::RenderPassInfo& getRenderPassInfo(RenderGraph::vertex_descriptor u) const; + + RenderingInfo getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph& resg) const; + + LayoutAccess getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const; + + // those resource been moved point to another resID + ResourceGraph::vertex_descriptor realResourceID(const ccstd::pmr::string& name) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + const PmrTransparentMap& rasterViews, + boost::container::pmr::memory_resource* scratch) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + boost::container::pmr::memory_resource* scratch) const; + + ResourceAccessGraph resourceAccessGraph; + ResourceGraph& resourceGraph; + const RenderGraph& renderGraph; + const LayoutGraphData& layoutGraph; + boost::container::pmr::memory_resource* scratch{nullptr}; + RelationGraph relationGraph; + bool _enablePassReorder{false}; + bool _enableAutoBarrier{true}; + bool _enableMemoryAliasing{false}; + bool _accessGraphBuilt{false}; + float _paralellExecWeight{0.0F}; +}; + +} // namespace render + +} // namespace cc + +// clang-format on From 0385078e7be2edb5471a465c2406b25f63d496d3 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 9 Aug 2023 18:41:37 +0800 Subject: [PATCH 11/82] fix addTexture default plane --- .../renderer/pipeline/custom/RenderInterfaceTypes.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 476d09c6f48..d4925ff87d7 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -1002,10 +1002,10 @@ class RenderSubpassBuilder : public Setter { addDepthStencil(name, accessType, depthSlotName, stencilSlotName, loadOp, storeOp, depth, stencil, gfx::ClearFlagBit::DEPTH_STENCIL); } void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0); + addTexture(name, slotName, nullptr, 0xFFFFFFFF); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0); + addTexture(name, slotName, sampler, 0xFFFFFFFF); } RenderQueueBuilder *addQueue() { return addQueue(QueueHint::NONE, "default"); @@ -1149,10 +1149,10 @@ class ComputeSubpassBuilder : public Setter { */ virtual void setCustomShaderStages(const ccstd::string &name, gfx::ShaderStageFlagBit stageFlags) = 0; void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0); + addTexture(name, slotName, nullptr, 0xFFFFFFFF); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0); + addTexture(name, slotName, sampler, 0xFFFFFFFF); } ComputeQueueBuilder *addQueue() { return addQueue("default"); @@ -1308,10 +1308,10 @@ class ComputePassBuilder : public Setter { */ virtual void setCustomShaderStages(const ccstd::string &name, gfx::ShaderStageFlagBit stageFlags) = 0; void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0); + addTexture(name, slotName, nullptr, 0xFFFFFFFF); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0); + addTexture(name, slotName, sampler, 0xFFFFFFFF); } void addMaterialTexture(const ccstd::string &resourceName) { addMaterialTexture(resourceName, gfx::ShaderStageFlagBit::COMPUTE); From ed75fb87de3f28ff26e64e77c151378148f37eff Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 9 Aug 2023 18:54:25 +0800 Subject: [PATCH 12/82] change default planeID to 0 --- .../pipeline/custom/RenderInterfaceTypes.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index d4925ff87d7..77845fd5c64 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -649,10 +649,10 @@ class BasicRenderPassBuilder : public Setter { addDepthStencil(name, loadOp, storeOp, depth, stencil, gfx::ClearFlagBit::DEPTH_STENCIL); } void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0xFFFFFFFF); + addTexture(name, slotName, nullptr, 0); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0xFFFFFFFF); + addTexture(name, slotName, sampler, 0); } RenderQueueBuilder *addQueue() { return addQueue(QueueHint::NONE, "default"); @@ -1002,10 +1002,10 @@ class RenderSubpassBuilder : public Setter { addDepthStencil(name, accessType, depthSlotName, stencilSlotName, loadOp, storeOp, depth, stencil, gfx::ClearFlagBit::DEPTH_STENCIL); } void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0xFFFFFFFF); + addTexture(name, slotName, nullptr, 0); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0xFFFFFFFF); + addTexture(name, slotName, sampler, 0); } RenderQueueBuilder *addQueue() { return addQueue(QueueHint::NONE, "default"); @@ -1149,10 +1149,10 @@ class ComputeSubpassBuilder : public Setter { */ virtual void setCustomShaderStages(const ccstd::string &name, gfx::ShaderStageFlagBit stageFlags) = 0; void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0xFFFFFFFF); + addTexture(name, slotName, nullptr, 0); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0xFFFFFFFF); + addTexture(name, slotName, sampler, 0); } ComputeQueueBuilder *addQueue() { return addQueue("default"); @@ -1308,10 +1308,10 @@ class ComputePassBuilder : public Setter { */ virtual void setCustomShaderStages(const ccstd::string &name, gfx::ShaderStageFlagBit stageFlags) = 0; void addTexture(const ccstd::string &name, const ccstd::string &slotName) { - addTexture(name, slotName, nullptr, 0xFFFFFFFF); + addTexture(name, slotName, nullptr, 0); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler) { - addTexture(name, slotName, sampler, 0xFFFFFFFF); + addTexture(name, slotName, sampler, 0); } void addMaterialTexture(const ccstd::string &resourceName) { addMaterialTexture(resourceName, gfx::ShaderStageFlagBit::COMPUTE); From ddad5a14a066b59f3fe3ee9c05365b50373ab6aa Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Thu, 10 Aug 2023 14:36:05 +0800 Subject: [PATCH 13/82] remove [nodiscard] string literal (#161) --- .../cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index c9913176111..56c3a9c40f5 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -122,7 +122,7 @@ ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccst return resourceAccessGraph.resourceIndex.at(name); } -[[nodiscard("concat")]] ccstd::pmr::string concatResName( +[[nodiscard]] ccstd::pmr::string concatResName( std::string_view name0, std::string_view name1, boost::container::pmr::memory_resource *scratch) { @@ -132,7 +132,7 @@ ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccst return name; } -[[nodiscard("subresName")]] ccstd::pmr::string getSubresNameByPlane(const ccstd::pmr::string &resName, +[[nodiscard]] ccstd::pmr::string getSubresNameByPlane(const ccstd::pmr::string &resName, uint32_t planeID, const ResourceGraph &resg, boost::container::pmr::memory_resource *scratch) { const auto &desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); @@ -1476,7 +1476,7 @@ bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const Resour return check; } -[[nodiscard("subres_name")]] ccstd::pmr::string getSubresourceNameByRange( +[[nodiscard]] ccstd::pmr::string getSubresourceNameByRange( const gfx::ResourceRange &range, boost::container::pmr::memory_resource *scratch) { ccstd::pmr::string subresName(scratch); From 60a89e24e1a1a72a2c800c236b919e40df24343a Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 10 Aug 2023 16:13:29 +0800 Subject: [PATCH 14/82] fix naming --- .../renderer/pipeline/custom/FGDispatcherTypes.h | 12 ++++++------ .../pipeline/custom/FrameGraphDispatcher.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h index 369d9460a0f..4f6b586f6f4 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h @@ -123,7 +123,7 @@ struct FGRenderPassInfo { FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; - std::vector colorAccesses; + ccstd::vector colorAccesses; LayoutAccess dsAccess; LayoutAccess dsResolveAccess; gfx::RenderPassInfo rpInfo; @@ -144,23 +144,23 @@ struct Barrier { }; struct BarrierNode { - std::vector frontBarriers; - std::vector rearBarriers; + ccstd::vector frontBarriers; + ccstd::vector rearBarriers; }; struct SliceNode { bool full{false}; - std::vector mips; + ccstd::vector mips; }; struct TextureNode { bool full{false}; - std::vector slices; + ccstd::vector slices; }; struct ResourceNode { bool full{false}; - std::vector planes; + ccstd::vector planes; }; struct ResourceAccessGraph { diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 56c3a9c40f5..d18121f8761 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -365,11 +365,11 @@ LayoutAccess FrameGraphDispatcher::getResourceAccess(ResourceGraph::vertex_descr using PmrString = ccstd::pmr::string; using EdgeList = std::pair; using CloseCircuit = std::pair; -using CloseCircuits = std::vector; +using CloseCircuits = ccstd::vector; using RelationVert = RelationGraph::vertex_descriptor; -using RelationVerts = std::vector; +using RelationVerts = ccstd::vector; using RelationEdge = RelationGraph::edge_descriptor; -using RelationEdges = std::vector; +using RelationEdges = ccstd::vector; using ScoreMap = std::map>; using RasterViewsMap = PmrTransparentMap; using ComputeViewsMap = PmrTransparentMap>; @@ -2418,7 +2418,7 @@ void passReorder(FrameGraphDispatcher &fgDispatcher) { boost::transitive_closure(relationGraph, relationGraphTc); CloseCircuits circuits; - std::vector crossEdges; + ccstd::vector crossEdges; PassVisitor visitor(relationGraphTc, circuits); auto colors = relationGraph.colors(scratch); boost::depth_first_search(relationGraph, visitor, get(colors, relationGraph)); @@ -2446,7 +2446,7 @@ void passReorder(FrameGraphDispatcher &fgDispatcher) { RelationVerts candidates; candidates.push_back(EXPECT_START_ID); - std::vector candidateBuffer; + ccstd::vector candidateBuffer; uint32_t coloredVerts = 0; while (coloredVerts < relationGraph._vertices.size()) { // decreasing order, pop back from vector, push into queue, then it's ascending order. From e5faac9d22885edfb8489e374640218bf56bdea6 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 10 Aug 2023 18:01:48 +0800 Subject: [PATCH 15/82] [Fixed]Clean up redundant code and fix an issue where adjusting the color of the skybox affects the color of the scene sampling image. --- cocos/rendering/custom/define.ts | 26 +----- cocos/rendering/custom/executor.ts | 84 +++++++++++++------ cocos/rendering/custom/web-pipeline.ts | 21 +++-- .../post-process/passes/forward-final-pass.ts | 4 +- .../post-process/passes/forward-pass.ts | 4 +- .../post-process/utils/pass-context.ts | 31 +++---- 6 files changed, 92 insertions(+), 78 deletions(-) diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index b131e820357..54300dc05dc 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -1206,33 +1206,13 @@ export function updateGlobalDescBinding (data: RenderData, layoutName = 'default applyGlobalDescBinding(data, layoutName, true); } -export function mergeSrcToTargetDesc (fromDesc, toDesc, isForce = false): number[] { +export function mergeSrcToTargetDesc (fromDesc, toDesc): number[] { fromDesc.update(); const fromGpuDesc = fromDesc.gpuDescriptorSet; const toGpuDesc = toDesc.gpuDescriptorSet; const extResId: number[] = []; - if (isForce) { - toGpuDesc.gpuDescriptors = fromGpuDesc.gpuDescriptors; - toGpuDesc.descriptorIndices = fromGpuDesc.descriptorIndices; - return extResId; - } - for (let i = 0; i < toGpuDesc.gpuDescriptors.length; i++) { - const fromRes = fromGpuDesc.gpuDescriptors[i]; - if (!fromRes) continue; - const currRes = toGpuDesc.gpuDescriptors[i]; - if (!currRes.gpuBuffer && fromRes.gpuBuffer) { - currRes.gpuBuffer = fromRes.gpuBuffer; - extResId.push(i); - } else if ('gpuTextureView' in currRes && !currRes.gpuTextureView) { - currRes.gpuTextureView = fromRes.gpuTextureView; - currRes.gpuSampler = fromRes.gpuSampler; - extResId.push(i); - } else if ('gpuTexture' in currRes && !currRes.gpuTexture) { - currRes.gpuTexture = fromRes.gpuTexture; - currRes.gpuSampler = fromRes.gpuSampler; - extResId.push(i); - } - } + toGpuDesc.gpuDescriptors = fromGpuDesc.gpuDescriptors; + toGpuDesc.descriptorIndices = fromGpuDesc.descriptorIndices; return extResId; } diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 445a712e1ed..42f95c9b9b5 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -59,7 +59,6 @@ import { Rect, RenderPass, RenderPassInfo, - Shader, StoreOp, SurfaceTransform, Swapchain, @@ -76,7 +75,7 @@ import { Pass } from '../../render-scene'; import { Camera } from '../../render-scene/scene/camera'; import { ShadowType } from '../../render-scene/scene/shadows'; import { Root } from '../../root'; -import { IRenderPass, isEnableEffect, SetIndex, UBODeferredLight, UBOForwardLight, UBOLocal } from '../define'; +import { IRenderPass, SetIndex, UBODeferredLight, UBOForwardLight, UBOLocal } from '../define'; import { PipelineSceneData } from '../pipeline-scene-data'; import { PipelineInputAssemblerData } from '../render-pipeline'; import { DescriptorSetData, LayoutGraphData, PipelineLayoutData, RenderPhaseData, RenderStageData } from './layout-graph'; @@ -122,23 +121,19 @@ import { UpdateFrequency, } from './types'; import { PipelineUBO } from '../pipeline-ubo'; -import { RenderInfo, RenderObject, WebSceneTask, WebSceneTransversal } from './web-scene'; +import { WebSceneTask, WebSceneTransversal } from './web-scene'; import { WebSceneVisitor } from './web-scene-visitor'; import { RenderAdditiveLightQueue } from '../render-additive-light-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; import { - getDescBindingFromName, getDescriptorSetDataFromLayout, getDescriptorSetDataFromLayoutId, getRenderArea, mergeSrcToTargetDesc, updateGlobalDescBinding, - validPunctualLightsCulling, } from './define'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; -import { builtinResMgr } from '../../asset/asset-manager/builtin-res-mgr'; -import { Texture2D } from '../../asset/assets/texture-2d'; import { SceneCulling } from './scene-culling'; class ResourceVisitor implements ResourceGraphVisitor { @@ -163,6 +158,7 @@ class ResourceVisitor implements ResourceGraphVisitor { // noop } persistentBuffer (value: Buffer): void { + // do nothing } persistentTexture (value: Texture): void { this.createDeviceTex(value); @@ -174,8 +170,10 @@ class ResourceVisitor implements ResourceGraphVisitor { this.createDeviceTex(value); } formatView (value: FormatView): void { + // do nothing } subresourceView (value: SubresourceView): void { + // do nothing } } @@ -884,7 +882,7 @@ class DeviceRenderPass { ia, ); const descData = getDescriptorSetDataFromLayoutId(pass.passID)!; - mergeSrcToTargetDesc(descData.descriptorSet, context.pipeline.descriptorSet, true); + mergeSrcToTargetDesc(descData.descriptorSet, context.pipeline.descriptorSet); profilerViewport.width = rect.width; profilerViewport.height = rect.height; cmdBuff.setViewport(profilerViewport); @@ -1258,7 +1256,7 @@ class DeviceSceneTask extends WebSceneTask { const layoutName = context.renderGraph.getLayout(rasterId); const descSetData = getDescriptorSetDataFromLayout(layoutName); - mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet, true); + mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet); this._currentQueue.isUpdateUBO = true; } @@ -1729,13 +1727,27 @@ class PreRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor { this.currPass.resetResource(this.passID, pass); } } - rasterSubpass (value: RasterSubpass): void {} - computeSubpass (value: ComputeSubpass): void {} - compute (value: ComputePass): void {} - resolve (value: ResolvePass): void {} - copy (value: CopyPass): void {} - move (value: MovePass): void {} - raytrace (value: RaytracePass): void {} + rasterSubpass (value: RasterSubpass): void { + // do nothing + } + computeSubpass (value: ComputeSubpass): void { + // do nothing + } + compute (value: ComputePass): void { + // do nothing + } + resolve (value: ResolvePass): void { + // do nothing + } + copy (value: CopyPass): void { + // do nothing + } + move (value: MovePass): void { + // do nothing + } + raytrace (value: RaytracePass): void { + // do nothing + } queue (value: RenderQueue): void { if (!this.rg.getValid(this.queueID)) return; const deviceQueue = context.pools.addDeviceQueue(); @@ -1763,7 +1775,9 @@ class PreRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor { graphScene.init(null, value, -1); this.currQueue!.addSceneTask(graphScene); } - dispatch (value: Dispatch): void {} + dispatch (value: Dispatch): void { + // do nothing + } } class PostRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor { @@ -1786,21 +1800,39 @@ class PostRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor this.currPass.record(); this.currPass.postPass(); } - rasterSubpass (value: RasterSubpass): void {} - computeSubpass (value: ComputeSubpass): void {} - resolve (value: ResolvePass): void {} - compute (value: ComputePass): void {} - copy (value: CopyPass): void {} - move (value: MovePass): void {} - raytrace (value: RaytracePass): void {} + rasterSubpass (value: RasterSubpass): void { + // do nothing + } + computeSubpass (value: ComputeSubpass): void { + // do nothing + } + resolve (value: ResolvePass): void { + // do nothing + } + compute (value: ComputePass): void { + // do nothing + } + copy (value: CopyPass): void { + // do nothing + } + move (value: MovePass): void { + // do nothing + } + raytrace (value: RaytracePass): void { + // do nothing + } queue (value: RenderQueue): void { // collect scene results } scene (value: SceneData): void { // scene command list finished } - blit (value: Blit): void {} - dispatch (value: Dispatch): void {} + blit (value: Blit): void { + // do nothing + } + dispatch (value: Dispatch): void { + // do nothing + } } export class RenderVisitor extends DefaultVisitor { diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 08e171ab45c..590037c7721 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -38,7 +38,7 @@ import { Executor } from './executor'; import { RenderWindow } from '../../render-scene/core/render-window'; import { MacroRecord, RenderScene } from '../../render-scene'; import { GlobalDSManager } from '../global-descriptor-set-manager'; -import { isEnableEffect, supportsR32FloatTexture, supportsRGBA16HalfFloatTexture, UBOSkinning } from '../define'; +import { supportsR32FloatTexture, supportsRGBA16HalfFloatTexture, UBOSkinning } from '../define'; import { OS } from '../../../pal/system-info/enum-type'; import { Compiler } from './compiler'; import { PipelineUBO } from '../pipeline-ubo'; @@ -255,16 +255,16 @@ export class WebSetter { this._data.samplers.set(num, sampler); } public setBuiltinCameraConstants (camera: Camera): void { - + // do nothing } public setBuiltinShadowMapConstants (light: Light, numLevels?: number): void { - + // do nothing } public setBuiltinDirectionalLightViewConstants (light: DirectionalLight): void { - + // do nothing } public setBuiltinSpotLightViewConstants (light: SpotLight): void { - + // do nothing } public hasSampler (name: string): boolean { const id = this._lg.attributeIndex.get(name); @@ -829,7 +829,7 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild getLayoutName (): string { const parId = this._renderGraph.getParent(this._vertID); - const layoutName = isEnableEffect() ? this._renderGraph.getLayout(parId) : 'default'; + const layoutName = this._renderGraph.getLayout(parId); return layoutName; } @@ -1084,7 +1084,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR this._pass.rasterViews.set(name, view); } resolveRenderTarget (source: string, target: string): void { - + // do nothing } resolveDepthStencil ( source: string, @@ -1092,7 +1092,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR depthMode?: ResolveMode, stencilMode?: ResolveMode, ): void { - + // do nothing } private _addComputeResource (name: string, accessType: AccessType, slotName: string): void { const view = new ComputeView(slotName); @@ -1587,8 +1587,7 @@ export class WebPipeline implements BasicPipeline { this._globalDescSetData = this.getGlobalDescriptorSetData()!; this._globalDescriptorSetLayout = this._globalDescSetData.descriptorSetLayout; this._globalDescriptorSetInfo = new DescriptorSetInfo(this._globalDescriptorSetLayout!); - this._globalDescriptorSet = isEnableEffect() ? this._device.createDescriptorSet(this._globalDescriptorSetInfo) - : this._globalDescSetData.descriptorSet; + this._globalDescriptorSet = this._device.createDescriptorSet(this._globalDescriptorSetInfo); this._globalDSManager.globalDescriptorSet = this.globalDescriptorSet; this._compileMaterial(); this.setMacroBool('CC_USE_HDR', this._pipelineSceneData.isHDR); @@ -1933,7 +1932,7 @@ export class WebPipeline implements BasicPipeline { const data = new RenderData(); const vertID = this._renderGraph!.addVertex(RenderGraphValue.RasterPass, pass, name, layoutName, data, false); const result = new WebRenderPassBuilder(data, this._renderGraph!, this._layoutGraph, this._resourceGraph, vertID, pass, this._pipelineSceneData); - this._updateRasterPassConstants(result, width, height, isEnableEffect() ? layoutName : 'default'); + this._updateRasterPassConstants(result, width, height, layoutName); initGlobalDescBinding(data, layoutName); return result; } diff --git a/cocos/rendering/post-process/passes/forward-final-pass.ts b/cocos/rendering/post-process/passes/forward-final-pass.ts index 06372f2c185..e12220833fc 100644 --- a/cocos/rendering/post-process/passes/forward-final-pass.ts +++ b/cocos/rendering/post-process/passes/forward-final-pass.ts @@ -12,7 +12,7 @@ import { BasePass } from './base-pass'; export class ForwardFinalPass extends BasePass { name = 'ForwardFinalPass'; - outputNames = ['ForwardFinalColor'] + outputNames = ['ForwardFinalColor']; enableInAllEditorCamera = true; @@ -21,7 +21,7 @@ export class ForwardFinalPass extends BasePass { return; } - passContext.clearFlag = camera.clearFlag & ClearFlagBit.COLOR; + passContext.clearFlag = camera.clearFlag; Vec4.set(passContext.clearColor, camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w); passContext.material = this.material; diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index e81630d80d2..5d4320c1648 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -1,7 +1,7 @@ import { Vec4 } from '../../../core'; import { ClearFlagBit, Format } from '../../../gfx'; -import { Camera } from '../../../render-scene/scene'; +import { Camera, SKYBOX_FLAG } from '../../../render-scene/scene'; import { LightInfo, QueueHint, SceneFlags } from '../../custom/types'; import { getCameraUniqueID } from '../../custom/define'; import { Pipeline } from '../../custom/pipeline'; @@ -37,7 +37,7 @@ export class ForwardPass extends BasePass { } public render (camera: Camera, ppl: Pipeline): void { - passContext.clearFlag = ClearFlagBit.COLOR | (camera.clearFlag & ClearFlagBit.DEPTH_STENCIL); + passContext.clearFlag = camera.clearFlag; Vec4.set(passContext.clearColor, 0, 0, 0, 0); Vec4.set(passContext.clearDepthColor, camera.clearDepth, camera.clearStencil, 0, 0); diff --git a/cocos/rendering/post-process/utils/pass-context.ts b/cocos/rendering/post-process/utils/pass-context.ts index a3677222b70..323fa4411c3 100644 --- a/cocos/rendering/post-process/utils/pass-context.ts +++ b/cocos/rendering/post-process/utils/pass-context.ts @@ -3,7 +3,7 @@ import { EDITOR } from 'internal:constants'; import { QueueHint, ResourceResidency, SceneFlags } from '../../custom/types'; import { ClearFlagBit, Color, Format, LoadOp, Rect, StoreOp, Viewport } from '../../../gfx'; import { Pipeline, RenderPassBuilder } from '../../custom/pipeline'; -import { Camera } from '../../../render-scene/scene'; +import { Camera, SKYBOX_FLAG } from '../../../render-scene/scene'; import { Material } from '../../../asset/assets'; import { PostProcess } from '../components'; import { getRenderArea } from '../../custom/define'; @@ -11,15 +11,15 @@ import { Vec4 } from '../../../core'; export class PassContext { clearFlag: ClearFlagBit = ClearFlagBit.COLOR; - clearColor = new Color() - clearDepthColor = new Color() - ppl: Pipeline| undefined - camera: Camera| undefined - material: Material| undefined - pass: RenderPassBuilder| undefined - rasterWidth = 0 - rasterHeight = 0 - layoutName = '' + clearColor = new Color(); + clearDepthColor = new Color(); + ppl: Pipeline| undefined; + camera: Camera| undefined; + material: Material| undefined; + pass: RenderPassBuilder| undefined; + rasterWidth = 0; + rasterHeight = 0; + layoutName = ''; shadingScale = 1; viewport = new Rect(); @@ -154,10 +154,11 @@ export class PassContext { const clearFlag = this.clearFlag & ClearFlagBit.COLOR; let loadOp = LoadOp.CLEAR; - if (clearFlag === ClearFlagBit.NONE) { + if (clearFlag === ClearFlagBit.NONE && !(this.clearFlag & SKYBOX_FLAG)) { loadOp = LoadOp.LOAD; + } else if (this.clearFlag & SKYBOX_FLAG) { + clearColor.set(0, 0, 0, 1); } - pass.addRenderTarget(name, loadOp, StoreOp.STORE, clearColor); } return this; @@ -171,8 +172,10 @@ export class PassContext { blitScreen (passIdx = 0): PassContext { this.pass!.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - this.camera!, this.material!, passIdx, - SceneFlags.NONE, + this.camera!, +this.material!, +passIdx, +SceneFlags.NONE, ); return this; } From bf9866e3a9ed377744f316805feed0669d2d5707 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 10 Aug 2023 18:18:20 +0800 Subject: [PATCH 16/82] Update eslint --- cocos/rendering/custom/executor.ts | 4 +++- cocos/rendering/forward/forward-stage.ts | 11 +++++++++-- cocos/rendering/post-process/utils/pass-context.ts | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 42f95c9b9b5..44671703809 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1145,7 +1145,9 @@ class DeviceSceneTask extends WebSceneTask { } } get graphScene (): GraphScene { return this._graphScene; } - public start (): void {} + public start (): void { + // do nothing + } protected _recordUI (): void { const batches = this.camera!.scene!.batches; diff --git a/cocos/rendering/forward/forward-stage.ts b/cocos/rendering/forward/forward-stage.ts index 3a486735198..86a6f2dde06 100644 --- a/cocos/rendering/forward/forward-stage.ts +++ b/cocos/rendering/forward/forward-stage.ts @@ -122,6 +122,7 @@ export class ForwardStage extends RenderStage { } public destroy (): void { + // do nothing } public render (camera: Camera): void { @@ -179,8 +180,14 @@ export class ForwardStage extends RenderStage { const framebuffer = camera.window.framebuffer; const renderPass = pipeline.getRenderPass(camera.clearFlag & this._clearFlag, framebuffer); - cmdBuff.beginRenderPass(renderPass, framebuffer, this._renderArea, - colors, camera.clearDepth, camera.clearStencil); + cmdBuff.beginRenderPass( + renderPass, + framebuffer, + this._renderArea, + colors, + camera.clearDepth, + camera.clearStencil, + ); cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); this._renderQueues[0].recordCommandBuffer(device, renderPass, cmdBuff); diff --git a/cocos/rendering/post-process/utils/pass-context.ts b/cocos/rendering/post-process/utils/pass-context.ts index 323fa4411c3..0921cf0b717 100644 --- a/cocos/rendering/post-process/utils/pass-context.ts +++ b/cocos/rendering/post-process/utils/pass-context.ts @@ -111,7 +111,7 @@ export class PassContext { // return this; // } - addRasterView (name: string, format: Format, offscreen = true, residency?: ResourceResidency): PassContext { + addRasterView (name: string, format: Format, offscreen = true, residency: ResourceResidency = ResourceResidency.MANAGED): PassContext { const ppl = this.ppl; const camera = this.camera; const pass = this.pass; From 479e67a8fc4498ff40c373b5b604c352d75fe7e1 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 11 Aug 2023 14:05:16 +0800 Subject: [PATCH 17/82] [Fixed] Fix the issue of ghosting in the gizmo when moving the editor. --- cocos/rendering/post-process/passes/forward-final-pass.ts | 4 ++-- cocos/rendering/post-process/passes/forward-pass.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos/rendering/post-process/passes/forward-final-pass.ts b/cocos/rendering/post-process/passes/forward-final-pass.ts index e12220833fc..725a726ce14 100644 --- a/cocos/rendering/post-process/passes/forward-final-pass.ts +++ b/cocos/rendering/post-process/passes/forward-final-pass.ts @@ -4,7 +4,7 @@ import { Vec4 } from '../../../core'; import { director } from '../../../game'; import { ClearFlagBit, Format } from '../../../gfx'; -import { Camera } from '../../../render-scene/scene'; +import { Camera, SKYBOX_FLAG } from '../../../render-scene/scene'; import { getCameraUniqueID } from '../../custom/define'; import { Pipeline } from '../../custom/pipeline'; import { passContext } from '../utils/pass-context'; @@ -21,7 +21,7 @@ export class ForwardFinalPass extends BasePass { return; } - passContext.clearFlag = camera.clearFlag; + passContext.clearFlag = camera.clearFlag & ClearFlagBit.COLOR | (camera.clearFlag & SKYBOX_FLAG); Vec4.set(passContext.clearColor, camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w); passContext.material = this.material; diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index 5d4320c1648..d6ddf91fbdb 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -37,7 +37,7 @@ export class ForwardPass extends BasePass { } public render (camera: Camera, ppl: Pipeline): void { - passContext.clearFlag = camera.clearFlag; + passContext.clearFlag = ClearFlagBit.COLOR | (camera.clearFlag & ClearFlagBit.DEPTH_STENCIL) | (camera.clearFlag & SKYBOX_FLAG); Vec4.set(passContext.clearColor, 0, 0, 0, 0); Vec4.set(passContext.clearDepthColor, camera.clearDepth, camera.clearStencil, 0, 0); From 1c9ecc4ffebe72c281a5cd85b91415cd053c221a Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 11 Aug 2023 18:31:32 +0800 Subject: [PATCH 18/82] add object pool --- cocos/gfx/base/define.ts | 20 +++++ cocos/rendering/custom/layout-graph.ts | 38 +++++++- cocos/rendering/custom/render-graph.ts | 116 +++++++++++++++++++++++++ cocos/rendering/custom/types.ts | 84 ++++++++++++++++++ 4 files changed, 257 insertions(+), 1 deletion(-) diff --git a/cocos/gfx/base/define.ts b/cocos/gfx/base/define.ts index 6e614fb3630..e8b328ec628 100644 --- a/cocos/gfx/base/define.ts +++ b/cocos/gfx/base/define.ts @@ -979,6 +979,15 @@ export class Viewport { this.maxDepth = info.maxDepth; return this; } + + public reset (): void { + this.left = 0; + this.top = 0; + this.width = 0; + this.height = 0; + this.minDepth = 0; + this.maxDepth = 1; + } } export class Color { @@ -1006,6 +1015,13 @@ export class Color { this.w = w; return this; } + + public reset (): void { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + } } export class BindingMappingInfo { @@ -1756,6 +1772,10 @@ export class DescriptorSetLayoutInfo { deepCopy(this.bindings, info.bindings, DescriptorSetLayoutBinding); return this; } + + reset (): void { + this.bindings.length = 0; + } } export class DescriptorSetInfo { diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 9ec1346ce68..1b4f3d94d6d 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -587,6 +587,12 @@ export class UniformData { this.uniformType = uniformType; this.offset = offset; } + reset (uniformID = 0xFFFFFFFF, uniformType: Type = Type.UNKNOWN, offset = 0): void { + this.uniformID = uniformID; + this.uniformType = uniformType; + this.offset = offset; + this.size = 0; + } uniformID: number; uniformType: Type; offset: number; @@ -604,6 +610,11 @@ export class DescriptorData { this.type = type; this.count = count; } + reset (descriptorID = 0, type: Type = Type.UNKNOWN, count = 1): void { + this.descriptorID = descriptorID; + this.type = type; + this.count = count; + } descriptorID: number; type: Type; count: number; @@ -615,6 +626,13 @@ export class DescriptorBlockData { this.visibility = visibility; this.capacity = capacity; } + reset (type: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, capacity = 0): void { + this.type = type; + this.visibility = visibility; + this.offset = 0; + this.capacity = capacity; + this.descriptors.length = 0; + } type: DescriptorTypeOrder; visibility: ShaderStageFlagBit; offset = 0; @@ -636,6 +654,18 @@ export class DescriptorSetLayoutData { this.uniformBlocks = uniformBlocks; this.bindingMap = bindingMap; } + reset ( + slot = 0xFFFFFFFF, + capacity = 0, + ): void { + this.slot = slot; + this.capacity = capacity; + this.uniformBlockCapacity = 0; + this.samplerTextureCapacity = 0; + this.descriptorBlocks.length = 0; + this.uniformBlocks.clear(); + this.bindingMap.clear(); + } slot: number; capacity: number; uniformBlockCapacity = 0; @@ -651,6 +681,12 @@ export class DescriptorSetData { this.descriptorSetLayout = descriptorSetLayout; this.descriptorSet = descriptorSet; } + reset (descriptorSetLayout: DescriptorSetLayout | null = null, descriptorSet: DescriptorSet | null = null): void { + this.descriptorSetLayoutData.reset(); + this.descriptorSetLayoutInfo.reset(); + this.descriptorSetLayout = descriptorSetLayout; + this.descriptorSet = descriptorSet; + } readonly descriptorSetLayoutData: DescriptorSetLayoutData; readonly descriptorSetLayoutInfo: DescriptorSetLayoutInfo = new DescriptorSetLayoutInfo(); /*refcount*/ descriptorSetLayout: DescriptorSetLayout | null; @@ -1263,7 +1299,7 @@ export class LayoutGraphData implements BidirectionalGraph export function saveDescriptorDB (ar: OutputArchive, v: DescriptorDB): void { ar.writeNumber(v.blocks.size); // Map for (const [k1, v1] of v.blocks) { - saveDescriptorBlockIndex(ar, JSON.parse(k1)); + saveDescriptorBlockIndex(ar, JSON.parse(k1) as DescriptorBlockIndex); saveDescriptorBlock(ar, v1); } } diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 41078871395..2b3a2faacb1 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -43,6 +43,12 @@ export class ClearValue { this.z = z; this.w = w; } + reset (x = 0, y = 0, z = 0, w = 0): void { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } x: number; y: number; z: number; @@ -69,6 +75,26 @@ export class RasterView { this.clearColor = clearColor; this.shaderStageFlags = shaderStageFlags; } + reset ( + slotName = '', + accessType: AccessType = AccessType.WRITE, + attachmentType: AttachmentType = AttachmentType.RENDER_TARGET, + loadOp: LoadOp = LoadOp.LOAD, + storeOp: StoreOp = StoreOp.STORE, + clearFlags: ClearFlagBit = ClearFlagBit.ALL, + shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + ): void { + this.slotName = slotName; + this.slotName1 = ''; + this.accessType = accessType; + this.attachmentType = attachmentType; + this.loadOp = loadOp; + this.storeOp = storeOp; + this.clearFlags = clearFlags; + this.clearColor.reset(); + this.slotID = 0; + this.shaderStageFlags = shaderStageFlags; + } slotName: string; slotName1 = ''; accessType: AccessType; @@ -97,6 +123,21 @@ export class ComputeView { this.clearValue = clearValue; this.shaderStageFlags = shaderStageFlags; } + reset ( + name = '', + accessType: AccessType = AccessType.READ, + clearFlags: ClearFlagBit = ClearFlagBit.NONE, + clearValueType: ClearValueType = ClearValueType.NONE, + shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + ): void { + this.name = name; + this.accessType = accessType; + this.plane = 0; + this.clearFlags = clearFlags; + this.clearValueType = clearValueType; + this.clearValue.reset(); + this.shaderStageFlags = shaderStageFlags; + } name: string; accessType: AccessType; plane = 0; @@ -123,6 +164,9 @@ export class ResourceTraits { constructor (residency: ResourceResidency = ResourceResidency.MANAGED) { this.residency = residency; } + reset (residency: ResourceResidency = ResourceResidency.MANAGED): void { + this.residency = residency; + } residency: ResourceResidency; } @@ -130,6 +174,13 @@ export class RenderSwapchain { constructor (swapchain: Swapchain | null = null) { this.swapchain = swapchain; } + reset (swapchain: Swapchain | null = null): void { + this.swapchain = swapchain; + this.renderWindow = null; + this.currentID = 0; + this.numBackBuffers = 0; + this.generation = 0xFFFFFFFF; + } /*pointer*/ swapchain: Swapchain | null; /*pointer*/ renderWindow: RenderWindow | null = null; currentID = 0; @@ -145,6 +196,10 @@ export class ManagedBuffer { constructor (buffer: Buffer | null = null) { this.buffer = buffer; } + reset (buffer: Buffer | null = null): void { + this.buffer = buffer; + this.fenceValue = 0; + } /*refcount*/ buffer: Buffer | null; fenceValue = 0; } @@ -153,6 +208,10 @@ export class ManagedTexture { constructor (texture: Texture | null = null) { this.texture = texture; } + reset (texture: Texture | null = null): void { + this.texture = texture; + this.fenceValue = 0; + } /*refcount*/ texture: Texture | null; fenceValue = 0; } @@ -474,6 +533,16 @@ export class RasterSubpass { this.count = count; this.quality = quality; } + reset (subpassID: number, count: number, quality: number): void { + this.rasterViews.clear(); + this.computeViews.clear(); + this.resolvePairs.length = 0; + this.viewport.reset(); + this.subpassID = subpassID; + this.count = count; + this.quality = quality; + this.showStatistics = false; + } readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); readonly resolvePairs: ResolvePair[] = []; @@ -488,6 +557,11 @@ export class ComputeSubpass { constructor (subpassID: number) { this.subpassID = subpassID; } + reset (subpassID: number): void { + this.rasterViews.clear(); + this.computeViews.clear(); + this.subpassID = subpassID; + } readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); subpassID: number; @@ -515,6 +589,13 @@ export class PersistentRenderPassAndFramebuffer { this.renderPass = renderPass; this.framebuffer = framebuffer; } + reset (renderPass: RenderPass, framebuffer: Framebuffer): void { + this.renderPass = renderPass; + this.framebuffer = framebuffer; + this.clearColors.length = 0; + this.clearDepth = 0; + this.clearStencil = 0; + } /*refcount*/ renderPass: RenderPass; /*refcount*/ framebuffer: Framebuffer; readonly clearColors: Color[] = []; @@ -1316,6 +1397,11 @@ export class ClearView { this.clearFlags = clearFlags; this.clearColor = clearColor; } + reset (slotName = '', clearFlags: ClearFlagBit = ClearFlagBit.ALL): void { + this.slotName = slotName; + this.clearFlags = clearFlags; + this.clearColor.reset(); + } slotName: string; clearFlags: ClearFlagBit; readonly clearColor: Color; @@ -1326,6 +1412,11 @@ export class RenderQueue { this.hint = hint; this.phaseID = phaseID; } + reset (hint: QueueHint = QueueHint.RENDER_OPAQUE, phaseID = 0xFFFFFFFF): void { + this.hint = hint; + this.phaseID = phaseID; + this.viewport = null; + } hint: QueueHint; phaseID: number; viewport: Viewport | null = null; @@ -1338,6 +1429,12 @@ export class SceneData { this.light = light; this.flags = flags; } + reset (scene: RenderScene | null = null, camera: Camera | null = null, flags: SceneFlags = SceneFlags.NONE): void { + this.scene = scene; + this.camera = camera; + this.light.reset(); + this.flags = flags; + } /*pointer*/ scene: RenderScene | null; /*pointer*/ camera: Camera | null; readonly light: LightInfo; @@ -1358,6 +1455,19 @@ export class Dispatch { this.threadGroupCountY = threadGroupCountY; this.threadGroupCountZ = threadGroupCountZ; } + reset ( + material: Material | null, + passID: number, + threadGroupCountX: number, + threadGroupCountY: number, + threadGroupCountZ: number, + ): void { + this.material = material; + this.passID = passID; + this.threadGroupCountX = threadGroupCountX; + this.threadGroupCountY = threadGroupCountY; + this.threadGroupCountZ = threadGroupCountZ; + } /*refcount*/ material: Material | null; passID: number; threadGroupCountX: number; @@ -1372,6 +1482,12 @@ export class Blit { this.sceneFlags = sceneFlags; this.camera = camera; } + reset (material: Material | null, passID: number, sceneFlags: SceneFlags, camera: Camera | null): void { + this.material = material; + this.passID = passID; + this.sceneFlags = sceneFlags; + this.camera = camera; + } /*refcount*/ material: Material | null; passID: number; sceneFlags: SceneFlags; diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index bde9ca132f7..163b587b54d 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -293,6 +293,11 @@ export class LightInfo { this.level = level; this.culledByLight = culledByLight; } + reset (light: Light | null = null, level = 0, culledByLight = false): void { + this.light = light; + this.level = level; + this.culledByLight = culledByLight; + } /*refcount*/ light: Light | null; level: number; culledByLight: boolean; @@ -339,6 +344,10 @@ export class Descriptor { constructor (type: Type = Type.UNKNOWN) { this.type = type; } + reset (type: Type = Type.UNKNOWN): void { + this.type = type; + this.count = 1; + } type: Type; count = 1; } @@ -366,6 +375,12 @@ export class DescriptorBlockIndex { this.descriptorType = descriptorType; this.visibility = visibility; } + reset (updateFrequency: UpdateFrequency = UpdateFrequency.PER_INSTANCE, parameterType: ParameterType = ParameterType.CONSTANTS, descriptorType: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE): void { + this.updateFrequency = updateFrequency; + this.parameterType = parameterType; + this.descriptorType = descriptorType; + this.visibility = visibility; + } updateFrequency: UpdateFrequency; parameterType: ParameterType; descriptorType: DescriptorTypeOrder; @@ -393,6 +408,19 @@ export class ResolvePair { this.mode = mode; this.mode1 = mode1; } + reset ( + source = '', + target = '', + resolveFlags: ResolveFlags = ResolveFlags.NONE, + mode: ResolveMode = ResolveMode.SAMPLE_ZERO, + mode1: ResolveMode = ResolveMode.SAMPLE_ZERO, + ): void { + this.source = source; + this.target = target; + this.resolveFlags = resolveFlags; + this.mode = mode; + this.mode1 = mode1; + } source: string; target: string; resolveFlags: ResolveFlags; @@ -424,6 +452,29 @@ export class CopyPair { this.targetFirstSlice = targetFirstSlice; this.targetPlaneSlice = targetPlaneSlice; } + reset ( + source = '', + target = '', + mipLevels = 0xFFFFFFFF, + numSlices = 0xFFFFFFFF, + sourceMostDetailedMip = 0, + sourceFirstSlice = 0, + sourcePlaneSlice = 0, + targetMostDetailedMip = 0, + targetFirstSlice = 0, + targetPlaneSlice = 0, + ): void { + this.source = source; + this.target = target; + this.mipLevels = mipLevels; + this.numSlices = numSlices; + this.sourceMostDetailedMip = sourceMostDetailedMip; + this.sourceFirstSlice = sourceFirstSlice; + this.sourcePlaneSlice = sourcePlaneSlice; + this.targetMostDetailedMip = targetMostDetailedMip; + this.targetFirstSlice = targetFirstSlice; + this.targetPlaneSlice = targetPlaneSlice; + } source: string; target: string; mipLevels: number; @@ -454,6 +505,22 @@ export class UploadPair { this.targetFirstSlice = targetFirstSlice; this.targetPlaneSlice = targetPlaneSlice; } + reset ( + target = '', + mipLevels = 0xFFFFFFFF, + numSlices = 0xFFFFFFFF, + targetMostDetailedMip = 0, + targetFirstSlice = 0, + targetPlaneSlice = 0, + ): void { + // source: Uint8Array size unchanged + this.target = target; + this.mipLevels = mipLevels; + this.numSlices = numSlices; + this.targetMostDetailedMip = targetMostDetailedMip; + this.targetFirstSlice = targetFirstSlice; + this.targetPlaneSlice = targetPlaneSlice; + } readonly source: Uint8Array; target: string; mipLevels: number; @@ -481,6 +548,23 @@ export class MovePair { this.targetFirstSlice = targetFirstSlice; this.targetPlaneSlice = targetPlaneSlice; } + reset ( + source = '', + target = '', + mipLevels = 0xFFFFFFFF, + numSlices = 0xFFFFFFFF, + targetMostDetailedMip = 0, + targetFirstSlice = 0, + targetPlaneSlice = 0, + ): void { + this.source = source; + this.target = target; + this.mipLevels = mipLevels; + this.numSlices = numSlices; + this.targetMostDetailedMip = targetMostDetailedMip; + this.targetFirstSlice = targetFirstSlice; + this.targetPlaneSlice = targetPlaneSlice; + } source: string; target: string; mipLevels: number; From 378ed5fbf49cbee4d15ada6d14dca1b102fefcdd Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 11 Aug 2023 18:40:45 +0800 Subject: [PATCH 19/82] skip index reset --- cocos/rendering/custom/types.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 163b587b54d..747d982a630 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -375,12 +375,6 @@ export class DescriptorBlockIndex { this.descriptorType = descriptorType; this.visibility = visibility; } - reset (updateFrequency: UpdateFrequency = UpdateFrequency.PER_INSTANCE, parameterType: ParameterType = ParameterType.CONSTANTS, descriptorType: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE): void { - this.updateFrequency = updateFrequency; - this.parameterType = parameterType; - this.descriptorType = descriptorType; - this.visibility = visibility; - } updateFrequency: UpdateFrequency; parameterType: ParameterType; descriptorType: DescriptorTypeOrder; From a24e954c6d335572f8f9e35a6f8122ba95e5e1db Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 14 Aug 2023 11:15:33 +0800 Subject: [PATCH 20/82] add reset --- cocos/rendering/custom/layout-graph.ts | 39 +++++++++++++ cocos/rendering/custom/render-graph.ts | 76 ++++++++++++++++++++++++++ cocos/rendering/custom/types.ts | 27 +++++++++ cocos/rendering/custom/web-types.ts | 4 ++ 4 files changed, 146 insertions(+) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 1b4f3d94d6d..488dda3ad0c 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -35,10 +35,16 @@ import { OutputArchive, InputArchive } from './archive'; import { saveUniformBlock, loadUniformBlock, saveDescriptorSetLayoutInfo, loadDescriptorSetLayoutInfo } from './serialization'; export class DescriptorDB { + reset (): void { + this.blocks.clear(); + } readonly blocks: Map = new Map(); } export class RenderPhase { + reset (): void { + this.shaders.clear(); + } readonly shaders: Set = new Set(); } @@ -600,6 +606,10 @@ export class UniformData { } export class UniformBlockData { + reset (): void { + this.bufferSize = 0; + this.uniforms.length = 0; + } bufferSize = 0; readonly uniforms: UniformData[] = []; } @@ -694,36 +704,65 @@ export class DescriptorSetData { } export class PipelineLayoutData { + reset (): void { + this.descriptorSets.clear(); + } readonly descriptorSets: Map = new Map(); } export class ShaderBindingData { + reset (): void { + this.descriptorBindings.clear(); + } readonly descriptorBindings: Map = new Map(); } export class ShaderLayoutData { + reset (): void { + this.layoutData.clear(); + this.bindingData.clear(); + } readonly layoutData: Map = new Map(); readonly bindingData: Map = new Map(); } export class TechniqueData { + reset (): void { + this.passes.length = 0; + } readonly passes: ShaderLayoutData[] = []; } export class EffectData { + reset (): void { + this.techniques.clear(); + } readonly techniques: Map = new Map(); } export class ShaderProgramData { + reset (): void { + this.layout.reset(); + this.pipelineLayout = null; + } readonly layout: PipelineLayoutData = new PipelineLayoutData(); /*refcount*/ pipelineLayout: PipelineLayout | null = null; } export class RenderStageData { + reset (): void { + this.descriptorVisibility.clear(); + } readonly descriptorVisibility: Map = new Map(); } export class RenderPhaseData { + reset (): void { + this.rootSignature = ''; + this.shaderPrograms.length = 0; + this.shaderIndex.clear(); + this.pipelineLayout = null; + } rootSignature = ''; readonly shaderPrograms: ShaderProgramData[] = []; readonly shaderIndex: Map = new Map(); diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 2b3a2faacb1..8ae43aa9b76 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -148,6 +148,18 @@ export class ComputeView { } export class ResourceDesc { + reset (): void { + this.dimension = ResourceDimension.BUFFER; + this.alignment = 0; + this.width = 0; + this.height = 0; + this.depthOrArraySize = 0; + this.mipLevels = 0; + this.format = Format.UNKNOWN; + this.sampleCount = SampleCount.X1; + this.textureFlags = TextureFlagBit.NONE; + this.flags = ResourceFlags.NONE; + } dimension: ResourceDimension = ResourceDimension.BUFFER; alignment = 0; width = 0; @@ -189,6 +201,9 @@ export class RenderSwapchain { } export class ResourceStates { + reset (): void { + this.states = AccessFlagBit.NONE; + } states: AccessFlagBit = AccessFlagBit.NONE; } @@ -217,10 +232,18 @@ export class ManagedTexture { } export class ManagedResource { + reset (): void { + this.unused = 0; + } unused = 0; } export class Subpass { + reset (): void { + this.rasterViews.clear(); + this.computeViews.clear(); + this.resolvePairs.length = 0; + } readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); readonly resolvePairs: ResolvePair[] = []; @@ -568,6 +591,22 @@ export class ComputeSubpass { } export class RasterPass { + reset (): void { + this.rasterViews.clear(); + this.computeViews.clear(); + this.attachmentIndexMap.clear(); + this.textures.clear(); + this.subpassGraph.clear(); + this.width = 0; + this.height = 0; + this.count = 1; + this.quality = 0; + this.viewport.reset(); + this.versionName = ''; + this.version = 0; + this.hashValue = 0; + this.showStatistics = false; + } readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); readonly attachmentIndexMap: Map = new Map(); @@ -604,10 +643,23 @@ export class PersistentRenderPassAndFramebuffer { } export class FormatView { + reset (): void { + this.format = Format.UNKNOWN; + } format: Format = Format.UNKNOWN; } export class SubresourceView { + reset (): void { + this.textureView = null; + this.format = Format.UNKNOWN; + this.indexOrFirstMipLevel = 0; + this.numMipLevels = 0; + this.firstArraySlice = 0; + this.numArraySlices = 0; + this.firstPlane = 0; + this.numPlanes = 0; + } /*refcount*/ textureView: Texture | null = null; format: Format = Format.UNKNOWN; indexOrFirstMipLevel = 0; @@ -1370,24 +1422,41 @@ export class ResourceGraph implements BidirectionalGraph } export class ComputePass { + reset (): void { + this.computeViews.clear(); + this.textures.clear(); + } readonly computeViews: Map = new Map(); readonly textures: Map = new Map(); } export class ResolvePass { + reset (): void { + this.resolvePairs.length = 0; + } readonly resolvePairs: ResolvePair[] = []; } export class CopyPass { + reset (): void { + this.copyPairs.length = 0; + this.uploadPairs.length = 0; + } readonly copyPairs: CopyPair[] = []; readonly uploadPairs: UploadPair[] = []; } export class MovePass { + reset (): void { + this.movePairs.length = 0; + } readonly movePairs: MovePair[] = []; } export class RaytracePass { + reset (): void { + this.computeViews.clear(); + } readonly computeViews: Map = new Map(); } @@ -1495,6 +1564,13 @@ export class Blit { } export class RenderData { + reset (): void { + this.constants.clear(); + this.buffers.clear(); + this.textures.clear(); + this.samplers.clear(); + this.custom = ''; + } readonly constants: Map = new Map(); readonly buffers: Map = new Map(); readonly textures: Map = new Map(); diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 747d982a630..e674bba8d29 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -353,6 +353,12 @@ export class Descriptor { } export class DescriptorBlock { + reset (): void { + this.descriptors.clear(); + this.uniformBlocks.clear(); + this.capacity = 0; + this.count = 0; + } readonly descriptors: Map = new Map(); readonly uniformBlocks: Map = new Map(); capacity = 0; @@ -360,6 +366,14 @@ export class DescriptorBlock { } export class DescriptorBlockFlattened { + reset (): void { + this.descriptorNames.length = 0; + this.uniformBlockNames.length = 0; + this.descriptors.length = 0; + this.uniformBlocks.length = 0; + this.capacity = 0; + this.count = 0; + } readonly descriptorNames: string[] = []; readonly uniformBlockNames: string[] = []; readonly descriptors: Descriptor[] = []; @@ -569,6 +583,19 @@ export class MovePair { } export class PipelineStatistics { + reset (): void { + this.numRenderPasses = 0; + this.numManagedTextures = 0; + this.totalManagedTextures = 0; + this.numUploadBuffers = 0; + this.numUploadBufferViews = 0; + this.numFreeUploadBuffers = 0; + this.numFreeUploadBufferViews = 0; + this.numDescriptorSets = 0; + this.numFreeDescriptorSets = 0; + this.numInstancingBuffers = 0; + this.numInstancingUniformBlocks = 0; + } numRenderPasses = 0; numManagedTextures = 0; totalManagedTextures = 0; diff --git a/cocos/rendering/custom/web-types.ts b/cocos/rendering/custom/web-types.ts index b275b9abde9..1c329219d02 100644 --- a/cocos/rendering/custom/web-types.ts +++ b/cocos/rendering/custom/web-types.ts @@ -54,6 +54,10 @@ export class ProgramInfo { } export class ProgramGroup { + reset (): void { + this.programInfos.clear(); + this.programProxies.clear(); + } readonly programInfos: Map = new Map(); readonly programProxies: Map = new Map(); } From 4d4c9926f30d783ca615d59a86b0cd4a9e83aa1a Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 14 Aug 2023 11:38:13 +0800 Subject: [PATCH 21/82] remove unnecessary reset --- cocos/rendering/custom/web-types.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cocos/rendering/custom/web-types.ts b/cocos/rendering/custom/web-types.ts index 1c329219d02..b275b9abde9 100644 --- a/cocos/rendering/custom/web-types.ts +++ b/cocos/rendering/custom/web-types.ts @@ -54,10 +54,6 @@ export class ProgramInfo { } export class ProgramGroup { - reset (): void { - this.programInfos.clear(); - this.programProxies.clear(); - } readonly programInfos: Map = new Map(); readonly programProxies: Map = new Map(); } From 08142566926c8f0afa24d9e24e6adf15f511adb1 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 14 Aug 2023 15:38:53 +0800 Subject: [PATCH 22/82] adding object pool --- cocos/rendering/custom/layout-graph.ts | 50 ++++++++++++++++- cocos/rendering/custom/render-graph.ts | 76 +++++++++++++++++++++++++- cocos/rendering/custom/types.ts | 28 ++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 488dda3ad0c..fc71d25786e 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -30,7 +30,7 @@ /* eslint-disable max-len */ import { AddressableGraph, AdjI, AdjacencyGraph, BidirectionalGraph, ComponentGraph, ED, InEI, MutableGraph, MutableReferenceGraph, NamedGraph, OutE, OutEI, PolymorphicGraph, PropertyGraph, PropertyMap, ReferenceGraph, VertexListGraph, directional, findRelative, getPath, parallel, reindexEdgeList, traversal } from './graph'; import { DescriptorSet, DescriptorSetLayout, DescriptorSetLayoutInfo, PipelineLayout, ShaderStageFlagBit, Type, UniformBlock } from '../../gfx'; -import { DescriptorBlock, saveDescriptorBlock, loadDescriptorBlock, DescriptorBlockIndex, saveDescriptorBlockIndex, loadDescriptorBlockIndex, DescriptorTypeOrder, UpdateFrequency } from './types'; +import { DescriptorBlock, saveDescriptorBlock, loadDescriptorBlock, DescriptorBlockIndex, saveDescriptorBlockIndex, loadDescriptorBlockIndex, DescriptorTypeOrder, UpdateFrequency, RenderCommonObjectPool } from './types'; import { OutputArchive, InputArchive } from './archive'; import { saveUniformBlock, loadUniformBlock, saveDescriptorSetLayoutInfo, loadDescriptorSetLayoutInfo } from './serialization'; @@ -1335,6 +1335,54 @@ export class LayoutGraphData implements BidirectionalGraph constantMacros = ''; } +export class LayoutGraphObjectPoolSettings { + constructor (batchSize: number) { + this.descriptorDBBatchSize = batchSize; + this.renderPhaseBatchSize = batchSize; + this.layoutGraphBatchSize = batchSize; + this.uniformDataBatchSize = batchSize; + this.uniformBlockDataBatchSize = batchSize; + this.descriptorDataBatchSize = batchSize; + this.descriptorBlockDataBatchSize = batchSize; + this.descriptorSetLayoutDataBatchSize = batchSize; + this.descriptorSetDataBatchSize = batchSize; + this.pipelineLayoutDataBatchSize = batchSize; + this.shaderBindingDataBatchSize = batchSize; + this.shaderLayoutDataBatchSize = batchSize; + this.techniqueDataBatchSize = batchSize; + this.effectDataBatchSize = batchSize; + this.shaderProgramDataBatchSize = batchSize; + this.renderStageDataBatchSize = batchSize; + this.renderPhaseDataBatchSize = batchSize; + this.layoutGraphDataBatchSize = batchSize; + } + descriptorDBBatchSize = 0; + renderPhaseBatchSize = 0; + layoutGraphBatchSize = 0; + uniformDataBatchSize = 0; + uniformBlockDataBatchSize = 0; + descriptorDataBatchSize = 0; + descriptorBlockDataBatchSize = 0; + descriptorSetLayoutDataBatchSize = 0; + descriptorSetDataBatchSize = 0; + pipelineLayoutDataBatchSize = 0; + shaderBindingDataBatchSize = 0; + shaderLayoutDataBatchSize = 0; + techniqueDataBatchSize = 0; + effectDataBatchSize = 0; + shaderProgramDataBatchSize = 0; + renderStageDataBatchSize = 0; + renderPhaseDataBatchSize = 0; + layoutGraphDataBatchSize = 0; +} + +export class LayoutGraphObjectPool { + constructor (renderCommon: RenderCommonObjectPool) { + this._renderCommon = renderCommon; + } + _renderCommon: RenderCommonObjectPool; +} + export function saveDescriptorDB (ar: OutputArchive, v: DescriptorDB): void { ar.writeNumber(v.blocks.size); // Map for (const [k1, v1] of v.blocks) { diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 8ae43aa9b76..d48a29f17ad 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -32,7 +32,7 @@ import { AdjI, AdjacencyGraph, BidirectionalGraph, ComponentGraph, ED, InEI, Mut import { Material } from '../../asset/assets'; import { Camera } from '../../render-scene/scene/camera'; import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp, RenderPass, SampleCount, Sampler, SamplerInfo, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureFlagBit, Viewport } from '../../gfx'; -import { AccessType, AttachmentType, ClearValueType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UploadPair } from './types'; +import { AccessType, AttachmentType, ClearValueType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UploadPair, RenderCommonObjectPool } from './types'; import { RenderScene } from '../../render-scene/core/render-scene'; import { RenderWindow } from '../../render-scene/core/render-window'; @@ -2461,3 +2461,77 @@ export class RenderGraph implements BidirectionalGraph readonly index: Map = new Map(); readonly sortedVertices: number[] = []; } + +export class RenderGraphObjectPoolSettings { + constructor (batchSize: number) { + this.clearValueBatchSize = batchSize; + this.rasterViewBatchSize = batchSize; + this.computeViewBatchSize = batchSize; + this.resourceDescBatchSize = batchSize; + this.resourceTraitsBatchSize = batchSize; + this.renderSwapchainBatchSize = batchSize; + this.resourceStatesBatchSize = batchSize; + this.managedBufferBatchSize = batchSize; + this.managedTextureBatchSize = batchSize; + this.managedResourceBatchSize = batchSize; + this.subpassBatchSize = batchSize; + this.subpassGraphBatchSize = batchSize; + this.rasterSubpassBatchSize = batchSize; + this.computeSubpassBatchSize = batchSize; + this.rasterPassBatchSize = batchSize; + this.persistentRenderPassAndFramebufferBatchSize = batchSize; + this.formatViewBatchSize = batchSize; + this.subresourceViewBatchSize = batchSize; + this.resourceGraphBatchSize = batchSize; + this.computePassBatchSize = batchSize; + this.resolvePassBatchSize = batchSize; + this.copyPassBatchSize = batchSize; + this.movePassBatchSize = batchSize; + this.raytracePassBatchSize = batchSize; + this.clearViewBatchSize = batchSize; + this.renderQueueBatchSize = batchSize; + this.sceneDataBatchSize = batchSize; + this.dispatchBatchSize = batchSize; + this.blitBatchSize = batchSize; + this.renderDataBatchSize = batchSize; + this.renderGraphBatchSize = batchSize; + } + clearValueBatchSize = 0; + rasterViewBatchSize = 0; + computeViewBatchSize = 0; + resourceDescBatchSize = 0; + resourceTraitsBatchSize = 0; + renderSwapchainBatchSize = 0; + resourceStatesBatchSize = 0; + managedBufferBatchSize = 0; + managedTextureBatchSize = 0; + managedResourceBatchSize = 0; + subpassBatchSize = 0; + subpassGraphBatchSize = 0; + rasterSubpassBatchSize = 0; + computeSubpassBatchSize = 0; + rasterPassBatchSize = 0; + persistentRenderPassAndFramebufferBatchSize = 0; + formatViewBatchSize = 0; + subresourceViewBatchSize = 0; + resourceGraphBatchSize = 0; + computePassBatchSize = 0; + resolvePassBatchSize = 0; + copyPassBatchSize = 0; + movePassBatchSize = 0; + raytracePassBatchSize = 0; + clearViewBatchSize = 0; + renderQueueBatchSize = 0; + sceneDataBatchSize = 0; + dispatchBatchSize = 0; + blitBatchSize = 0; + renderDataBatchSize = 0; + renderGraphBatchSize = 0; +} + +export class RenderGraphObjectPool { + constructor (renderCommon: RenderCommonObjectPool) { + this._renderCommon = renderCommon; + } + _renderCommon: RenderCommonObjectPool; +} diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index e674bba8d29..4b066321fc1 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -609,6 +609,34 @@ export class PipelineStatistics { numInstancingUniformBlocks = 0; } +export class RenderCommonObjectPoolSettings { + constructor (batchSize: number) { + this.lightInfoBatchSize = batchSize; + this.descriptorBatchSize = batchSize; + this.descriptorBlockBatchSize = batchSize; + this.descriptorBlockFlattenedBatchSize = batchSize; + this.descriptorBlockIndexBatchSize = batchSize; + this.resolvePairBatchSize = batchSize; + this.copyPairBatchSize = batchSize; + this.uploadPairBatchSize = batchSize; + this.movePairBatchSize = batchSize; + this.pipelineStatisticsBatchSize = batchSize; + } + lightInfoBatchSize = 0; + descriptorBatchSize = 0; + descriptorBlockBatchSize = 0; + descriptorBlockFlattenedBatchSize = 0; + descriptorBlockIndexBatchSize = 0; + resolvePairBatchSize = 0; + copyPairBatchSize = 0; + uploadPairBatchSize = 0; + movePairBatchSize = 0; + pipelineStatisticsBatchSize = 0; +} + +export class RenderCommonObjectPool { +} + export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { // skip, v.light: Light ar.writeNumber(v.level); From ae06698d08c88ca776b78bc7e82f7be63c7f7143 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 14 Aug 2023 16:09:37 +0800 Subject: [PATCH 23/82] adding object pool --- cocos/rendering/custom/layout-graph.ts | 45 ++++++- cocos/rendering/custom/render-graph.ts | 111 ++++++++++++++---- cocos/rendering/custom/types.ts | 23 ++++ .../pipeline/custom/RenderGraphTypes.cpp | 9 ++ .../pipeline/custom/RenderGraphTypes.h | 2 + 5 files changed, 162 insertions(+), 28 deletions(-) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index fc71d25786e..98c8e902498 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -33,6 +33,7 @@ import { DescriptorSet, DescriptorSetLayout, DescriptorSetLayoutInfo, PipelineLa import { DescriptorBlock, saveDescriptorBlock, loadDescriptorBlock, DescriptorBlockIndex, saveDescriptorBlockIndex, loadDescriptorBlockIndex, DescriptorTypeOrder, UpdateFrequency, RenderCommonObjectPool } from './types'; import { OutputArchive, InputArchive } from './archive'; import { saveUniformBlock, loadUniformBlock, saveDescriptorSetLayoutInfo, loadDescriptorSetLayoutInfo } from './serialization'; +import { RecyclePool } from '../../core/memop'; export class DescriptorDB { reset (): void { @@ -1377,10 +1378,46 @@ export class LayoutGraphObjectPoolSettings { } export class LayoutGraphObjectPool { - constructor (renderCommon: RenderCommonObjectPool) { - this._renderCommon = renderCommon; - } - _renderCommon: RenderCommonObjectPool; + constructor (settings: LayoutGraphObjectPoolSettings, renderCommon: RenderCommonObjectPool) { + this.renderCommon = renderCommon; + this._descriptorDB = new RecyclePool(() => new DescriptorDB(), settings.descriptorDBBatchSize); + this._renderPhase = new RecyclePool(() => new RenderPhase(), settings.renderPhaseBatchSize); + this._layoutGraph = new RecyclePool(() => new LayoutGraph(), settings.layoutGraphBatchSize); + this._uniformData = new RecyclePool(() => new UniformData(), settings.uniformDataBatchSize); + this._uniformBlockData = new RecyclePool(() => new UniformBlockData(), settings.uniformBlockDataBatchSize); + this._descriptorData = new RecyclePool(() => new DescriptorData(), settings.descriptorDataBatchSize); + this._descriptorBlockData = new RecyclePool(() => new DescriptorBlockData(), settings.descriptorBlockDataBatchSize); + this._descriptorSetLayoutData = new RecyclePool(() => new DescriptorSetLayoutData(), settings.descriptorSetLayoutDataBatchSize); + this._descriptorSetData = new RecyclePool(() => new DescriptorSetData(), settings.descriptorSetDataBatchSize); + this._pipelineLayoutData = new RecyclePool(() => new PipelineLayoutData(), settings.pipelineLayoutDataBatchSize); + this._shaderBindingData = new RecyclePool(() => new ShaderBindingData(), settings.shaderBindingDataBatchSize); + this._shaderLayoutData = new RecyclePool(() => new ShaderLayoutData(), settings.shaderLayoutDataBatchSize); + this._techniqueData = new RecyclePool(() => new TechniqueData(), settings.techniqueDataBatchSize); + this._effectData = new RecyclePool(() => new EffectData(), settings.effectDataBatchSize); + this._shaderProgramData = new RecyclePool(() => new ShaderProgramData(), settings.shaderProgramDataBatchSize); + this._renderStageData = new RecyclePool(() => new RenderStageData(), settings.renderStageDataBatchSize); + this._renderPhaseData = new RecyclePool(() => new RenderPhaseData(), settings.renderPhaseDataBatchSize); + this._layoutGraphData = new RecyclePool(() => new LayoutGraphData(), settings.layoutGraphDataBatchSize); + } + public readonly renderCommon: RenderCommonObjectPool; + private readonly _descriptorDB: RecyclePool; + private readonly _renderPhase: RecyclePool; + private readonly _layoutGraph: RecyclePool; + private readonly _uniformData: RecyclePool; + private readonly _uniformBlockData: RecyclePool; + private readonly _descriptorData: RecyclePool; + private readonly _descriptorBlockData: RecyclePool; + private readonly _descriptorSetLayoutData: RecyclePool; + private readonly _descriptorSetData: RecyclePool; + private readonly _pipelineLayoutData: RecyclePool; + private readonly _shaderBindingData: RecyclePool; + private readonly _shaderLayoutData: RecyclePool; + private readonly _techniqueData: RecyclePool; + private readonly _effectData: RecyclePool; + private readonly _shaderProgramData: RecyclePool; + private readonly _renderStageData: RecyclePool; + private readonly _renderPhaseData: RecyclePool; + private readonly _layoutGraphData: RecyclePool; } export function saveDescriptorDB (ar: OutputArchive, v: DescriptorDB): void { diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index d48a29f17ad..9aa60aa066b 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -35,6 +35,7 @@ import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp import { AccessType, AttachmentType, ClearValueType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UploadPair, RenderCommonObjectPool } from './types'; import { RenderScene } from '../../render-scene/core/render-scene'; import { RenderWindow } from '../../render-scene/core/render-window'; +import { RecyclePool } from '../../core/memop'; export class ClearValue { constructor (x = 0, y = 0, z = 0, w = 0) { @@ -551,12 +552,12 @@ export class SubpassGraph implements BidirectionalGraph } export class RasterSubpass { - constructor (subpassID: number, count: number, quality: number) { + constructor (subpassID = 0xFFFFFFFF, count = 1, quality = 0) { this.subpassID = subpassID; this.count = count; this.quality = quality; } - reset (subpassID: number, count: number, quality: number): void { + reset (subpassID = 0xFFFFFFFF, count = 1, quality = 0): void { this.rasterViews.clear(); this.computeViews.clear(); this.resolvePairs.length = 0; @@ -577,10 +578,10 @@ export class RasterSubpass { } export class ComputeSubpass { - constructor (subpassID: number) { + constructor (subpassID = 0xFFFFFFFF) { this.subpassID = subpassID; } - reset (subpassID: number): void { + reset (subpassID = 0xFFFFFFFF): void { this.rasterViews.clear(); this.computeViews.clear(); this.subpassID = subpassID; @@ -624,19 +625,19 @@ export class RasterPass { } export class PersistentRenderPassAndFramebuffer { - constructor (renderPass: RenderPass, framebuffer: Framebuffer) { + constructor (renderPass: RenderPass | null = null, framebuffer: Framebuffer | null = null) { this.renderPass = renderPass; this.framebuffer = framebuffer; } - reset (renderPass: RenderPass, framebuffer: Framebuffer): void { + reset (renderPass: RenderPass | null = null, framebuffer: Framebuffer | null = null): void { this.renderPass = renderPass; this.framebuffer = framebuffer; this.clearColors.length = 0; this.clearDepth = 0; this.clearStencil = 0; } - /*refcount*/ renderPass: RenderPass; - /*refcount*/ framebuffer: Framebuffer; + /*refcount*/ renderPass: RenderPass | null; + /*refcount*/ framebuffer: Framebuffer | null; readonly clearColors: Color[] = []; clearDepth = 0; clearStencil = 0; @@ -1512,11 +1513,11 @@ export class SceneData { export class Dispatch { constructor ( - material: Material | null, - passID: number, - threadGroupCountX: number, - threadGroupCountY: number, - threadGroupCountZ: number, + material: Material | null = null, + passID = 0, + threadGroupCountX = 0, + threadGroupCountY = 0, + threadGroupCountZ = 0, ) { this.material = material; this.passID = passID; @@ -1525,11 +1526,11 @@ export class Dispatch { this.threadGroupCountZ = threadGroupCountZ; } reset ( - material: Material | null, - passID: number, - threadGroupCountX: number, - threadGroupCountY: number, - threadGroupCountZ: number, + material: Material | null = null, + passID = 0, + threadGroupCountX = 0, + threadGroupCountY = 0, + threadGroupCountZ = 0, ): void { this.material = material; this.passID = passID; @@ -1545,13 +1546,13 @@ export class Dispatch { } export class Blit { - constructor (material: Material | null, passID: number, sceneFlags: SceneFlags, camera: Camera | null) { + constructor (material: Material | null = null, passID = 0, sceneFlags: SceneFlags = SceneFlags.NONE, camera: Camera | null = null) { this.material = material; this.passID = passID; this.sceneFlags = sceneFlags; this.camera = camera; } - reset (material: Material | null, passID: number, sceneFlags: SceneFlags, camera: Camera | null): void { + reset (material: Material | null = null, passID = 0, sceneFlags: SceneFlags = SceneFlags.NONE, camera: Camera | null = null): void { this.material = material; this.passID = passID; this.sceneFlags = sceneFlags; @@ -2530,8 +2531,70 @@ export class RenderGraphObjectPoolSettings { } export class RenderGraphObjectPool { - constructor (renderCommon: RenderCommonObjectPool) { - this._renderCommon = renderCommon; - } - _renderCommon: RenderCommonObjectPool; + constructor (settings: RenderGraphObjectPoolSettings, renderCommon: RenderCommonObjectPool) { + this.renderCommon = renderCommon; + this._clearValue = new RecyclePool(() => new ClearValue(), settings.clearValueBatchSize); + this._rasterView = new RecyclePool(() => new RasterView(), settings.rasterViewBatchSize); + this._computeView = new RecyclePool(() => new ComputeView(), settings.computeViewBatchSize); + this._resourceDesc = new RecyclePool(() => new ResourceDesc(), settings.resourceDescBatchSize); + this._resourceTraits = new RecyclePool(() => new ResourceTraits(), settings.resourceTraitsBatchSize); + this._renderSwapchain = new RecyclePool(() => new RenderSwapchain(), settings.renderSwapchainBatchSize); + this._resourceStates = new RecyclePool(() => new ResourceStates(), settings.resourceStatesBatchSize); + this._managedBuffer = new RecyclePool(() => new ManagedBuffer(), settings.managedBufferBatchSize); + this._managedTexture = new RecyclePool(() => new ManagedTexture(), settings.managedTextureBatchSize); + this._managedResource = new RecyclePool(() => new ManagedResource(), settings.managedResourceBatchSize); + this._subpass = new RecyclePool(() => new Subpass(), settings.subpassBatchSize); + this._subpassGraph = new RecyclePool(() => new SubpassGraph(), settings.subpassGraphBatchSize); + this._rasterSubpass = new RecyclePool(() => new RasterSubpass(), settings.rasterSubpassBatchSize); + this._computeSubpass = new RecyclePool(() => new ComputeSubpass(), settings.computeSubpassBatchSize); + this._rasterPass = new RecyclePool(() => new RasterPass(), settings.rasterPassBatchSize); + this._persistentRenderPassAndFramebuffer = new RecyclePool(() => new PersistentRenderPassAndFramebuffer(), settings.persistentRenderPassAndFramebufferBatchSize); + this._formatView = new RecyclePool(() => new FormatView(), settings.formatViewBatchSize); + this._subresourceView = new RecyclePool(() => new SubresourceView(), settings.subresourceViewBatchSize); + this._resourceGraph = new RecyclePool(() => new ResourceGraph(), settings.resourceGraphBatchSize); + this._computePass = new RecyclePool(() => new ComputePass(), settings.computePassBatchSize); + this._resolvePass = new RecyclePool(() => new ResolvePass(), settings.resolvePassBatchSize); + this._copyPass = new RecyclePool(() => new CopyPass(), settings.copyPassBatchSize); + this._movePass = new RecyclePool(() => new MovePass(), settings.movePassBatchSize); + this._raytracePass = new RecyclePool(() => new RaytracePass(), settings.raytracePassBatchSize); + this._clearView = new RecyclePool(() => new ClearView(), settings.clearViewBatchSize); + this._renderQueue = new RecyclePool(() => new RenderQueue(), settings.renderQueueBatchSize); + this._sceneData = new RecyclePool(() => new SceneData(), settings.sceneDataBatchSize); + this._dispatch = new RecyclePool(() => new Dispatch(), settings.dispatchBatchSize); + this._blit = new RecyclePool(() => new Blit(), settings.blitBatchSize); + this._renderData = new RecyclePool(() => new RenderData(), settings.renderDataBatchSize); + this._renderGraph = new RecyclePool(() => new RenderGraph(), settings.renderGraphBatchSize); + } + public readonly renderCommon: RenderCommonObjectPool; + private readonly _clearValue: RecyclePool; + private readonly _rasterView: RecyclePool; + private readonly _computeView: RecyclePool; + private readonly _resourceDesc: RecyclePool; + private readonly _resourceTraits: RecyclePool; + private readonly _renderSwapchain: RecyclePool; + private readonly _resourceStates: RecyclePool; + private readonly _managedBuffer: RecyclePool; + private readonly _managedTexture: RecyclePool; + private readonly _managedResource: RecyclePool; + private readonly _subpass: RecyclePool; + private readonly _subpassGraph: RecyclePool; + private readonly _rasterSubpass: RecyclePool; + private readonly _computeSubpass: RecyclePool; + private readonly _rasterPass: RecyclePool; + private readonly _persistentRenderPassAndFramebuffer: RecyclePool; + private readonly _formatView: RecyclePool; + private readonly _subresourceView: RecyclePool; + private readonly _resourceGraph: RecyclePool; + private readonly _computePass: RecyclePool; + private readonly _resolvePass: RecyclePool; + private readonly _copyPass: RecyclePool; + private readonly _movePass: RecyclePool; + private readonly _raytracePass: RecyclePool; + private readonly _clearView: RecyclePool; + private readonly _renderQueue: RecyclePool; + private readonly _sceneData: RecyclePool; + private readonly _dispatch: RecyclePool; + private readonly _blit: RecyclePool; + private readonly _renderData: RecyclePool; + private readonly _renderGraph: RecyclePool; } diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 4b066321fc1..7ede91daaeb 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -32,6 +32,7 @@ import { ResolveMode, ShaderStageFlagBit, Type, UniformBlock } from '../../gfx'; import { Light } from '../../render-scene/scene'; import { OutputArchive, InputArchive } from './archive'; import { saveUniformBlock, loadUniformBlock } from './serialization'; +import { RecyclePool } from '../../core/memop'; export enum UpdateFrequency { PER_INSTANCE, @@ -635,6 +636,28 @@ export class RenderCommonObjectPoolSettings { } export class RenderCommonObjectPool { + constructor (settings: RenderCommonObjectPoolSettings) { + this._lightInfo = new RecyclePool(() => new LightInfo(), settings.lightInfoBatchSize); + this._descriptor = new RecyclePool(() => new Descriptor(), settings.descriptorBatchSize); + this._descriptorBlock = new RecyclePool(() => new DescriptorBlock(), settings.descriptorBlockBatchSize); + this._descriptorBlockFlattened = new RecyclePool(() => new DescriptorBlockFlattened(), settings.descriptorBlockFlattenedBatchSize); + this._descriptorBlockIndex = new RecyclePool(() => new DescriptorBlockIndex(), settings.descriptorBlockIndexBatchSize); + this._resolvePair = new RecyclePool(() => new ResolvePair(), settings.resolvePairBatchSize); + this._copyPair = new RecyclePool(() => new CopyPair(), settings.copyPairBatchSize); + this._uploadPair = new RecyclePool(() => new UploadPair(), settings.uploadPairBatchSize); + this._movePair = new RecyclePool(() => new MovePair(), settings.movePairBatchSize); + this._pipelineStatistics = new RecyclePool(() => new PipelineStatistics(), settings.pipelineStatisticsBatchSize); + } + private readonly _lightInfo: RecyclePool; + private readonly _descriptor: RecyclePool; + private readonly _descriptorBlock: RecyclePool; + private readonly _descriptorBlockFlattened: RecyclePool; + private readonly _descriptorBlockIndex: RecyclePool; + private readonly _resolvePair: RecyclePool; + private readonly _copyPair: RecyclePool; + private readonly _uploadPair: RecyclePool; + private readonly _movePair: RecyclePool; + private readonly _pipelineStatistics: RecyclePool; } export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.cpp b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.cpp index bcb977b9e35..46c87e4227e 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.cpp @@ -171,6 +171,11 @@ SubpassGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) : outEdges(rhs.outEdges, alloc), inEdges(rhs.inEdges, alloc) {} +RasterSubpass::RasterSubpass(const allocator_type& alloc) noexcept +: rasterViews(alloc), + computeViews(alloc), + resolvePairs(alloc) {} + RasterSubpass::RasterSubpass(uint32_t subpassIDIn, uint32_t countIn, uint32_t qualityIn, const allocator_type& alloc) noexcept : rasterViews(alloc), computeViews(alloc), @@ -199,6 +204,10 @@ RasterSubpass::RasterSubpass(RasterSubpass const& rhs, const allocator_type& all quality(rhs.quality), showStatistics(rhs.showStatistics) {} +ComputeSubpass::ComputeSubpass(const allocator_type& alloc) noexcept +: rasterViews(alloc), + computeViews(alloc) {} + ComputeSubpass::ComputeSubpass(uint32_t subpassIDIn, const allocator_type& alloc) noexcept : rasterViews(alloc), computeViews(alloc), diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h index acf43826fd8..ab4d719b712 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h @@ -389,6 +389,7 @@ struct RasterSubpass { return {rasterViews.get_allocator().resource()}; } + RasterSubpass(const allocator_type& alloc) noexcept; // NOLINT RasterSubpass(uint32_t subpassIDIn, uint32_t countIn, uint32_t qualityIn, const allocator_type& alloc) noexcept; RasterSubpass(RasterSubpass&& rhs, const allocator_type& alloc); RasterSubpass(RasterSubpass const& rhs, const allocator_type& alloc); @@ -414,6 +415,7 @@ struct ComputeSubpass { return {rasterViews.get_allocator().resource()}; } + ComputeSubpass(const allocator_type& alloc) noexcept; // NOLINT ComputeSubpass(uint32_t subpassIDIn, const allocator_type& alloc) noexcept; ComputeSubpass(ComputeSubpass&& rhs, const allocator_type& alloc); ComputeSubpass(ComputeSubpass const& rhs, const allocator_type& alloc); From a98ad1de3ff43443ec58344ba2ca867c417f82cd Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 14 Aug 2023 16:11:35 +0800 Subject: [PATCH 24/82] change default batch size --- cocos/rendering/custom/layout-graph.ts | 36 +++++++-------- cocos/rendering/custom/render-graph.ts | 62 +++++++++++++------------- cocos/rendering/custom/types.ts | 20 ++++----- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 98c8e902498..dfd3cc3f48f 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -1357,24 +1357,24 @@ export class LayoutGraphObjectPoolSettings { this.renderPhaseDataBatchSize = batchSize; this.layoutGraphDataBatchSize = batchSize; } - descriptorDBBatchSize = 0; - renderPhaseBatchSize = 0; - layoutGraphBatchSize = 0; - uniformDataBatchSize = 0; - uniformBlockDataBatchSize = 0; - descriptorDataBatchSize = 0; - descriptorBlockDataBatchSize = 0; - descriptorSetLayoutDataBatchSize = 0; - descriptorSetDataBatchSize = 0; - pipelineLayoutDataBatchSize = 0; - shaderBindingDataBatchSize = 0; - shaderLayoutDataBatchSize = 0; - techniqueDataBatchSize = 0; - effectDataBatchSize = 0; - shaderProgramDataBatchSize = 0; - renderStageDataBatchSize = 0; - renderPhaseDataBatchSize = 0; - layoutGraphDataBatchSize = 0; + descriptorDBBatchSize = 16; + renderPhaseBatchSize = 16; + layoutGraphBatchSize = 16; + uniformDataBatchSize = 16; + uniformBlockDataBatchSize = 16; + descriptorDataBatchSize = 16; + descriptorBlockDataBatchSize = 16; + descriptorSetLayoutDataBatchSize = 16; + descriptorSetDataBatchSize = 16; + pipelineLayoutDataBatchSize = 16; + shaderBindingDataBatchSize = 16; + shaderLayoutDataBatchSize = 16; + techniqueDataBatchSize = 16; + effectDataBatchSize = 16; + shaderProgramDataBatchSize = 16; + renderStageDataBatchSize = 16; + renderPhaseDataBatchSize = 16; + layoutGraphDataBatchSize = 16; } export class LayoutGraphObjectPool { diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 9aa60aa066b..4c1b442ca6a 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -2497,37 +2497,37 @@ export class RenderGraphObjectPoolSettings { this.renderDataBatchSize = batchSize; this.renderGraphBatchSize = batchSize; } - clearValueBatchSize = 0; - rasterViewBatchSize = 0; - computeViewBatchSize = 0; - resourceDescBatchSize = 0; - resourceTraitsBatchSize = 0; - renderSwapchainBatchSize = 0; - resourceStatesBatchSize = 0; - managedBufferBatchSize = 0; - managedTextureBatchSize = 0; - managedResourceBatchSize = 0; - subpassBatchSize = 0; - subpassGraphBatchSize = 0; - rasterSubpassBatchSize = 0; - computeSubpassBatchSize = 0; - rasterPassBatchSize = 0; - persistentRenderPassAndFramebufferBatchSize = 0; - formatViewBatchSize = 0; - subresourceViewBatchSize = 0; - resourceGraphBatchSize = 0; - computePassBatchSize = 0; - resolvePassBatchSize = 0; - copyPassBatchSize = 0; - movePassBatchSize = 0; - raytracePassBatchSize = 0; - clearViewBatchSize = 0; - renderQueueBatchSize = 0; - sceneDataBatchSize = 0; - dispatchBatchSize = 0; - blitBatchSize = 0; - renderDataBatchSize = 0; - renderGraphBatchSize = 0; + clearValueBatchSize = 16; + rasterViewBatchSize = 16; + computeViewBatchSize = 16; + resourceDescBatchSize = 16; + resourceTraitsBatchSize = 16; + renderSwapchainBatchSize = 16; + resourceStatesBatchSize = 16; + managedBufferBatchSize = 16; + managedTextureBatchSize = 16; + managedResourceBatchSize = 16; + subpassBatchSize = 16; + subpassGraphBatchSize = 16; + rasterSubpassBatchSize = 16; + computeSubpassBatchSize = 16; + rasterPassBatchSize = 16; + persistentRenderPassAndFramebufferBatchSize = 16; + formatViewBatchSize = 16; + subresourceViewBatchSize = 16; + resourceGraphBatchSize = 16; + computePassBatchSize = 16; + resolvePassBatchSize = 16; + copyPassBatchSize = 16; + movePassBatchSize = 16; + raytracePassBatchSize = 16; + clearViewBatchSize = 16; + renderQueueBatchSize = 16; + sceneDataBatchSize = 16; + dispatchBatchSize = 16; + blitBatchSize = 16; + renderDataBatchSize = 16; + renderGraphBatchSize = 16; } export class RenderGraphObjectPool { diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 7ede91daaeb..7f088da82e3 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -623,16 +623,16 @@ export class RenderCommonObjectPoolSettings { this.movePairBatchSize = batchSize; this.pipelineStatisticsBatchSize = batchSize; } - lightInfoBatchSize = 0; - descriptorBatchSize = 0; - descriptorBlockBatchSize = 0; - descriptorBlockFlattenedBatchSize = 0; - descriptorBlockIndexBatchSize = 0; - resolvePairBatchSize = 0; - copyPairBatchSize = 0; - uploadPairBatchSize = 0; - movePairBatchSize = 0; - pipelineStatisticsBatchSize = 0; + lightInfoBatchSize = 16; + descriptorBatchSize = 16; + descriptorBlockBatchSize = 16; + descriptorBlockFlattenedBatchSize = 16; + descriptorBlockIndexBatchSize = 16; + resolvePairBatchSize = 16; + copyPairBatchSize = 16; + uploadPairBatchSize = 16; + movePairBatchSize = 16; + pipelineStatisticsBatchSize = 16; } export class RenderCommonObjectPool { From 6d26cd6d494b3b5adcb4c0b4c1f6688b2c3f95ec Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 14 Aug 2023 16:18:06 +0800 Subject: [PATCH 25/82] reset added --- cocos/rendering/custom/layout-graph.ts | 20 ++++++++++++++++ cocos/rendering/custom/render-graph.ts | 33 ++++++++++++++++++++++++++ cocos/rendering/custom/types.ts | 12 ++++++++++ 3 files changed, 65 insertions(+) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index dfd3cc3f48f..f51c45c1180 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -1399,6 +1399,26 @@ export class LayoutGraphObjectPool { this._renderPhaseData = new RecyclePool(() => new RenderPhaseData(), settings.renderPhaseDataBatchSize); this._layoutGraphData = new RecyclePool(() => new LayoutGraphData(), settings.layoutGraphDataBatchSize); } + reset (): void { + this._descriptorDB.reset(); + this._renderPhase.reset(); + this._layoutGraph.reset(); + this._uniformData.reset(); + this._uniformBlockData.reset(); + this._descriptorData.reset(); + this._descriptorBlockData.reset(); + this._descriptorSetLayoutData.reset(); + this._descriptorSetData.reset(); + this._pipelineLayoutData.reset(); + this._shaderBindingData.reset(); + this._shaderLayoutData.reset(); + this._techniqueData.reset(); + this._effectData.reset(); + this._shaderProgramData.reset(); + this._renderStageData.reset(); + this._renderPhaseData.reset(); + this._layoutGraphData.reset(); + } public readonly renderCommon: RenderCommonObjectPool; private readonly _descriptorDB: RecyclePool; private readonly _renderPhase: RecyclePool; diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 4c1b442ca6a..45954f52130 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -2565,6 +2565,39 @@ export class RenderGraphObjectPool { this._renderData = new RecyclePool(() => new RenderData(), settings.renderDataBatchSize); this._renderGraph = new RecyclePool(() => new RenderGraph(), settings.renderGraphBatchSize); } + reset (): void { + this._clearValue.reset(); + this._rasterView.reset(); + this._computeView.reset(); + this._resourceDesc.reset(); + this._resourceTraits.reset(); + this._renderSwapchain.reset(); + this._resourceStates.reset(); + this._managedBuffer.reset(); + this._managedTexture.reset(); + this._managedResource.reset(); + this._subpass.reset(); + this._subpassGraph.reset(); + this._rasterSubpass.reset(); + this._computeSubpass.reset(); + this._rasterPass.reset(); + this._persistentRenderPassAndFramebuffer.reset(); + this._formatView.reset(); + this._subresourceView.reset(); + this._resourceGraph.reset(); + this._computePass.reset(); + this._resolvePass.reset(); + this._copyPass.reset(); + this._movePass.reset(); + this._raytracePass.reset(); + this._clearView.reset(); + this._renderQueue.reset(); + this._sceneData.reset(); + this._dispatch.reset(); + this._blit.reset(); + this._renderData.reset(); + this._renderGraph.reset(); + } public readonly renderCommon: RenderCommonObjectPool; private readonly _clearValue: RecyclePool; private readonly _rasterView: RecyclePool; diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 7f088da82e3..f65f0eefe9a 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -648,6 +648,18 @@ export class RenderCommonObjectPool { this._movePair = new RecyclePool(() => new MovePair(), settings.movePairBatchSize); this._pipelineStatistics = new RecyclePool(() => new PipelineStatistics(), settings.pipelineStatisticsBatchSize); } + reset (): void { + this._lightInfo.reset(); + this._descriptor.reset(); + this._descriptorBlock.reset(); + this._descriptorBlockFlattened.reset(); + this._descriptorBlockIndex.reset(); + this._resolvePair.reset(); + this._copyPair.reset(); + this._uploadPair.reset(); + this._movePair.reset(); + this._pipelineStatistics.reset(); + } private readonly _lightInfo: RecyclePool; private readonly _descriptor: RecyclePool; private readonly _descriptorBlock: RecyclePool; From 94889a23e4674ddaad089aec66087ee2084a0519 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 16 Aug 2023 17:00:26 +0800 Subject: [PATCH 26/82] add pool creation --- cocos/rendering/custom/layout-graph.ts | 108 +++++++++++++ cocos/rendering/custom/render-graph.ts | 212 +++++++++++++++++++++++++ cocos/rendering/custom/types.ts | 93 +++++++++++ 3 files changed, 413 insertions(+) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index f51c45c1180..4e8d25991dd 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -1419,6 +1419,114 @@ export class LayoutGraphObjectPool { this._renderPhaseData.reset(); this._layoutGraphData.reset(); } + createDescriptorDB (): DescriptorDB { + const v = this._descriptorDB.add(); + v.reset(); + return v; + } + createRenderPhase (): RenderPhase { + const v = this._renderPhase.add(); + v.reset(); + return v; + } + createLayoutGraph (): LayoutGraph { + const v = this._layoutGraph.add(); + v.clear(); + return v; + } + createUniformData ( + uniformID = 0xFFFFFFFF, + uniformType: Type = Type.UNKNOWN, + offset = 0, + ): UniformData { + const v = this._uniformData.add(); + v.reset(uniformID, uniformType, offset); + return v; + } + createUniformBlockData (): UniformBlockData { + const v = this._uniformBlockData.add(); + v.reset(); + return v; + } + createDescriptorData ( + descriptorID = 0, + type: Type = Type.UNKNOWN, + count = 1, + ): DescriptorData { + const v = this._descriptorData.add(); + v.reset(descriptorID, type, count); + return v; + } + createDescriptorBlockData ( + type: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, + visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + capacity = 0, + ): DescriptorBlockData { + const v = this._descriptorBlockData.add(); + v.reset(type, visibility, capacity); + return v; + } + createDescriptorSetLayoutData ( + slot = 0xFFFFFFFF, + capacity = 0, + ): DescriptorSetLayoutData { + const v = this._descriptorSetLayoutData.add(); + v.reset(slot, capacity); + return v; + } + createDescriptorSetData ( + descriptorSetLayout: DescriptorSetLayout | null = null, + descriptorSet: DescriptorSet | null = null, + ): DescriptorSetData { + const v = this._descriptorSetData.add(); + v.reset(descriptorSetLayout, descriptorSet); + return v; + } + createPipelineLayoutData (): PipelineLayoutData { + const v = this._pipelineLayoutData.add(); + v.reset(); + return v; + } + createShaderBindingData (): ShaderBindingData { + const v = this._shaderBindingData.add(); + v.reset(); + return v; + } + createShaderLayoutData (): ShaderLayoutData { + const v = this._shaderLayoutData.add(); + v.reset(); + return v; + } + createTechniqueData (): TechniqueData { + const v = this._techniqueData.add(); + v.reset(); + return v; + } + createEffectData (): EffectData { + const v = this._effectData.add(); + v.reset(); + return v; + } + createShaderProgramData (): ShaderProgramData { + const v = this._shaderProgramData.add(); + v.reset(); + return v; + } + createRenderStageData (): RenderStageData { + const v = this._renderStageData.add(); + v.reset(); + return v; + } + createRenderPhaseData (): RenderPhaseData { + const v = this._renderPhaseData.add(); + v.reset(); + return v; + } + createLayoutGraphData (): LayoutGraphData { + const v = this._layoutGraphData.add(); + v.clear(); + return v; + } public readonly renderCommon: RenderCommonObjectPool; private readonly _descriptorDB: RecyclePool; private readonly _renderPhase: RecyclePool; diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 45954f52130..1b0505b9fa4 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -2598,6 +2598,218 @@ export class RenderGraphObjectPool { this._renderData.reset(); this._renderGraph.reset(); } + createClearValue ( + x = 0, + y = 0, + z = 0, + w = 0, + ): ClearValue { + const v = this._clearValue.add(); + v.reset(x, y, z, w); + return v; + } + createRasterView ( + slotName = '', + accessType: AccessType = AccessType.WRITE, + attachmentType: AttachmentType = AttachmentType.RENDER_TARGET, + loadOp: LoadOp = LoadOp.LOAD, + storeOp: StoreOp = StoreOp.STORE, + clearFlags: ClearFlagBit = ClearFlagBit.ALL, + shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + ): RasterView { + const v = this._rasterView.add(); + v.reset(slotName, accessType, attachmentType, loadOp, storeOp, clearFlags, shaderStageFlags); + return v; + } + createComputeView ( + name = '', + accessType: AccessType = AccessType.READ, + clearFlags: ClearFlagBit = ClearFlagBit.NONE, + clearValueType: ClearValueType = ClearValueType.NONE, + shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + ): ComputeView { + const v = this._computeView.add(); + v.reset(name, accessType, clearFlags, clearValueType, shaderStageFlags); + return v; + } + createResourceDesc (): ResourceDesc { + const v = this._resourceDesc.add(); + v.reset(); + return v; + } + createResourceTraits ( + residency: ResourceResidency = ResourceResidency.MANAGED, + ): ResourceTraits { + const v = this._resourceTraits.add(); + v.reset(residency); + return v; + } + createRenderSwapchain ( + swapchain: Swapchain | null = null, + ): RenderSwapchain { + const v = this._renderSwapchain.add(); + v.reset(swapchain); + return v; + } + createResourceStates (): ResourceStates { + const v = this._resourceStates.add(); + v.reset(); + return v; + } + createManagedBuffer ( + buffer: Buffer | null = null, + ): ManagedBuffer { + const v = this._managedBuffer.add(); + v.reset(buffer); + return v; + } + createManagedTexture ( + texture: Texture | null = null, + ): ManagedTexture { + const v = this._managedTexture.add(); + v.reset(texture); + return v; + } + createManagedResource (): ManagedResource { + const v = this._managedResource.add(); + v.reset(); + return v; + } + createSubpass (): Subpass { + const v = this._subpass.add(); + v.reset(); + return v; + } + createSubpassGraph (): SubpassGraph { + const v = this._subpassGraph.add(); + v.clear(); + return v; + } + createRasterSubpass ( + subpassID = 0xFFFFFFFF, + count = 1, + quality = 0, + ): RasterSubpass { + const v = this._rasterSubpass.add(); + v.reset(subpassID, count, quality); + return v; + } + createComputeSubpass ( + subpassID = 0xFFFFFFFF, + ): ComputeSubpass { + const v = this._computeSubpass.add(); + v.reset(subpassID); + return v; + } + createRasterPass (): RasterPass { + const v = this._rasterPass.add(); + v.reset(); + return v; + } + createPersistentRenderPassAndFramebuffer ( + renderPass: RenderPass | null = null, + framebuffer: Framebuffer | null = null, + ): PersistentRenderPassAndFramebuffer { + const v = this._persistentRenderPassAndFramebuffer.add(); + v.reset(renderPass, framebuffer); + return v; + } + createFormatView (): FormatView { + const v = this._formatView.add(); + v.reset(); + return v; + } + createSubresourceView (): SubresourceView { + const v = this._subresourceView.add(); + v.reset(); + return v; + } + createResourceGraph (): ResourceGraph { + const v = this._resourceGraph.add(); + v.clear(); + return v; + } + createComputePass (): ComputePass { + const v = this._computePass.add(); + v.reset(); + return v; + } + createResolvePass (): ResolvePass { + const v = this._resolvePass.add(); + v.reset(); + return v; + } + createCopyPass (): CopyPass { + const v = this._copyPass.add(); + v.reset(); + return v; + } + createMovePass (): MovePass { + const v = this._movePass.add(); + v.reset(); + return v; + } + createRaytracePass (): RaytracePass { + const v = this._raytracePass.add(); + v.reset(); + return v; + } + createClearView ( + slotName = '', + clearFlags: ClearFlagBit = ClearFlagBit.ALL, + ): ClearView { + const v = this._clearView.add(); + v.reset(slotName, clearFlags); + return v; + } + createRenderQueue ( + hint: QueueHint = QueueHint.RENDER_OPAQUE, + phaseID = 0xFFFFFFFF, + ): RenderQueue { + const v = this._renderQueue.add(); + v.reset(hint, phaseID); + return v; + } + createSceneData ( + scene: RenderScene | null = null, + camera: Camera | null = null, + flags: SceneFlags = SceneFlags.NONE, + ): SceneData { + const v = this._sceneData.add(); + v.reset(scene, camera, flags); + return v; + } + createDispatch ( + material: Material | null = null, + passID = 0, + threadGroupCountX = 0, + threadGroupCountY = 0, + threadGroupCountZ = 0, + ): Dispatch { + const v = this._dispatch.add(); + v.reset(material, passID, threadGroupCountX, threadGroupCountY, threadGroupCountZ); + return v; + } + createBlit ( + material: Material | null = null, + passID = 0, + sceneFlags: SceneFlags = SceneFlags.NONE, + camera: Camera | null = null, + ): Blit { + const v = this._blit.add(); + v.reset(material, passID, sceneFlags, camera); + return v; + } + createRenderData (): RenderData { + const v = this._renderData.add(); + v.reset(); + return v; + } + createRenderGraph (): RenderGraph { + const v = this._renderGraph.add(); + v.clear(); + return v; + } public readonly renderCommon: RenderCommonObjectPool; private readonly _clearValue: RecyclePool; private readonly _rasterView: RecyclePool; diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index f65f0eefe9a..73d54641727 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -660,6 +660,99 @@ export class RenderCommonObjectPool { this._movePair.reset(); this._pipelineStatistics.reset(); } + createLightInfo ( + light: Light | null = null, + level = 0, + culledByLight = false, + ): LightInfo { + const v = this._lightInfo.add(); + v.reset(light, level, culledByLight); + return v; + } + createDescriptor ( + type: Type = Type.UNKNOWN, + ): Descriptor { + const v = this._descriptor.add(); + v.reset(type); + return v; + } + createDescriptorBlock (): DescriptorBlock { + const v = this._descriptorBlock.add(); + v.reset(); + return v; + } + createDescriptorBlockFlattened (): DescriptorBlockFlattened { + const v = this._descriptorBlockFlattened.add(); + v.reset(); + return v; + } + createDescriptorBlockIndex ( + updateFrequency: UpdateFrequency = UpdateFrequency.PER_INSTANCE, + parameterType: ParameterType = ParameterType.CONSTANTS, + descriptorType: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, + visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + ): DescriptorBlockIndex { + const v = this._descriptorBlockIndex.add(); + v.reset(updateFrequency, parameterType, descriptorType, visibility); + return v; + } + createResolvePair ( + source = '', + target = '', + resolveFlags: ResolveFlags = ResolveFlags.NONE, + mode: ResolveMode = ResolveMode.SAMPLE_ZERO, + mode1: ResolveMode = ResolveMode.SAMPLE_ZERO, + ): ResolvePair { + const v = this._resolvePair.add(); + v.reset(source, target, resolveFlags, mode, mode1); + return v; + } + createCopyPair ( + source = '', + target = '', + mipLevels = 0xFFFFFFFF, + numSlices = 0xFFFFFFFF, + sourceMostDetailedMip = 0, + sourceFirstSlice = 0, + sourcePlaneSlice = 0, + targetMostDetailedMip = 0, + targetFirstSlice = 0, + targetPlaneSlice = 0, + ): CopyPair { + const v = this._copyPair.add(); + v.reset(source, target, mipLevels, numSlices, sourceMostDetailedMip, sourceFirstSlice, sourcePlaneSlice, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); + return v; + } + createUploadPair ( + target = '', + mipLevels = 0xFFFFFFFF, + numSlices = 0xFFFFFFFF, + targetMostDetailedMip = 0, + targetFirstSlice = 0, + targetPlaneSlice = 0, + ): UploadPair { + const v = this._uploadPair.add(); + v.reset(target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); + return v; + } + createMovePair ( + source = '', + target = '', + mipLevels = 0xFFFFFFFF, + numSlices = 0xFFFFFFFF, + targetMostDetailedMip = 0, + targetFirstSlice = 0, + targetPlaneSlice = 0, + ): MovePair { + const v = this._movePair.add(); + v.reset(source, target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); + return v; + } + createPipelineStatistics (): PipelineStatistics { + const v = this._pipelineStatistics.add(); + v.reset(); + return v; + } private readonly _lightInfo: RecyclePool; private readonly _descriptor: RecyclePool; private readonly _descriptorBlock: RecyclePool; From f95ab81c790a355784cef347e332556d4ad56499 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 16 Aug 2023 17:23:10 +0800 Subject: [PATCH 27/82] fix reset bug --- cocos/rendering/custom/types.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 73d54641727..4d5952cfc6b 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -693,7 +693,10 @@ export class RenderCommonObjectPool { visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, ): DescriptorBlockIndex { const v = this._descriptorBlockIndex.add(); - v.reset(updateFrequency, parameterType, descriptorType, visibility); + v.updateFrequency = updateFrequency; + v.parameterType = parameterType; + v.descriptorType = descriptorType; + v.visibility = visibility; return v; } createResolvePair ( From 8b077f73050965faccea9f13b0f34aa220280150 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Wed, 16 Aug 2023 18:50:12 +0800 Subject: [PATCH 28/82] [Modify]Adjusting the logic of Reflection Probes --- cocos/rendering/custom/executor.ts | 22 +- cocos/rendering/custom/scene-culling.ts | 222 +++++++++++++------ cocos/rendering/custom/types.ts | 9 +- cocos/rendering/custom/web-pipeline-types.ts | 18 ++ 4 files changed, 182 insertions(+), 89 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 9e874b61c69..477b1a92f8e 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -71,7 +71,7 @@ import { import { legacyCC } from '../../core/global-exports'; import { Vec3 } from '../../core/math/vec3'; import { Vec4 } from '../../core/math/vec4'; -import { Pass } from '../../render-scene'; +import { IMacroPatch, Pass } from '../../render-scene'; import { Camera } from '../../render-scene/scene/camera'; import { ShadowType } from '../../render-scene/scene/shadows'; import { Root } from '../../root'; @@ -127,6 +127,7 @@ import { RenderAdditiveLightQueue } from '../render-additive-light-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; import { + bool, getDescriptorSetDataFromLayout, getDescriptorSetDataFromLayoutId, getRenderArea, @@ -1117,7 +1118,7 @@ class DevicePreSceneTask extends WebSceneTask { // this._uploadInstanceBuffers(); } } - +const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; const sceneViewport = new Viewport(); class DeviceSceneTask extends WebSceneTask { protected _currentQueue: DeviceRenderQueue; @@ -1177,17 +1178,6 @@ class DeviceSceneTask extends WebSceneTask { } } - protected _recordReflectionProbe (): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.reflectionProbe?.recordCommandBuffer( - context.device, - this._renderPass, - - context.commandBuffer, - ); - } - private _clearExtBlitDesc (desc, extResId: number[]): void { const toGpuDesc = desc.gpuDescriptorSet; for (let i = 0; i < extResId.length; i++) { @@ -1300,6 +1290,9 @@ class DeviceSceneTask extends WebSceneTask { renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); + if (!bool(graphSceneData.flags & SceneFlags.REFLECTION_PROBE) && graphSceneData.light.probe) { + renderQueue.opaqueQueue.removeMacro(CC_USE_RGBE_OUTPUT); + } if (graphSceneData.flags & SceneFlags.GEOMETRY) { this.camera!.geometryRenderer?.render( devicePass.renderPass, @@ -1310,9 +1303,6 @@ class DeviceSceneTask extends WebSceneTask { if (graphSceneData.flags & SceneFlags.UI) { this._recordUI(); } - if (graphSceneData.flags & SceneFlags.REFLECTION_PROBE) { - this._recordReflectionProbe(); - } } } diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 91c812521da..e20a6b5bbda 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -1,9 +1,10 @@ -import { Vec3, assert, RecyclePool, UpdateRecyclePool } from '../../core'; +import { Vec3, assert, RecyclePool, UpdateRecyclePool, cclegacy } from '../../core'; import { Frustum, intersect, AABB } from '../../core/geometry'; import { CommandBuffer } from '../../gfx'; -import { BatchingSchemes, Pass, RenderScene } from '../../render-scene'; -import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, SKYBOX_FLAG, ShadowType, SpotLight } from '../../render-scene/scene'; -import { Node } from '../../scene-graph'; +import { BatchingSchemes, IMacroPatch, Pass, RenderScene } from '../../render-scene'; +import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, ProbeType, + ReflectionProbe, SKYBOX_FLAG, ShadowType, SpotLight, SubModel } from '../../render-scene/scene'; +import { Layers, Node } from '../../scene-graph'; import { PipelineSceneData } from '../pipeline-scene-data'; import { hashCombineStr, getSubpassOrPassID, bool } from './define'; import { LayoutGraphData } from './layout-graph'; @@ -14,11 +15,10 @@ import { ObjectPool } from './utils'; const vec3Pool = new ObjectPool(() => new Vec3()); const cullingKeyRecycle = new RecyclePool(( - camera: Camera | null, - light: Light | null, + sceneData: SceneData, castShadows: boolean, - lightLevel: number, -) => new CullingKey(camera, light, castShadows, lightLevel), 0); + sceneId: number, +) => new CullingKey(sceneData, castShadows, sceneId), 0); const cullingQueriesRecycle = new RecyclePool(() => new CullingQueries(), 0); const renderQueueRecycle = new RecyclePool(() => new RenderQueue(), 0); const renderQueueDescRecycle = new RecyclePool(( @@ -26,8 +26,20 @@ const renderQueueDescRecycle = new RecyclePool(( renderQueueTarget: number, lightType: LightType, ) => new RenderQueueDesc(culledSource, renderQueueTarget, lightType), 0); -function computeCullingKey (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number): number { + +const REFLECTION_PROBE_DEFAULT_MASK = Layers.makeMaskExclude([Layers.BitMask.UI_2D, Layers.BitMask.UI_3D, + Layers.BitMask.GIZMOS, Layers.BitMask.EDITOR, + Layers.BitMask.SCENE_GIZMO, Layers.BitMask.PROFILER]); + +function computeCullingKey ( + sceneData: SceneData, + castShadows: boolean, +): number { let hashCode = 0; + const camera = sceneData.camera; + const light = sceneData.light.light; + const lightLevel = sceneData.light.level; + const reflectProbe = sceneData.light.probe; if (camera) { // camera hashCode = hashCombineStr(`u${camera.node.uuid}`, hashCode); @@ -64,26 +76,26 @@ function computeCullingKey (camera: Camera | null, light: Light | null, castShad } hashCode = hashCombineStr(`cast${castShadows}`, hashCode); hashCode = hashCombineStr(`level${lightLevel}`, hashCode); + if (reflectProbe) { + hashCode = hashCombineStr(`probe${reflectProbe.getProbeId()}`, hashCode); + } return hashCode; } class CullingKey extends UpdateRecyclePool { - camera: Camera | null; - light: Light | null; + sceneData: SceneData; castShadows = false; - lightLevel = 0xffffffff; - constructor (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number) { + sceneId = -1; + constructor (sceneData: SceneData, castShadows: boolean, verId: number) { super(); - this.camera = camera; - this.light = light; + this.sceneData = sceneData; this.castShadows = castShadows; - this.lightLevel = lightLevel; + this.sceneId = verId; } - update (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number): void { - this.camera = camera; - this.light = light; + update (sceneData: SceneData, castShadows: boolean, verId: number): void { + this.sceneData = sceneData; this.castShadows = castShadows; - this.lightLevel = lightLevel; + this.sceneId = verId; } } @@ -106,6 +118,11 @@ function isNodeVisible (node: Node, visibility: number): boolean { function isModelVisible (model: Model, visibility: number): boolean { return !!(visibility & model.visFlags); } + +function isReflectProbeMask (model: Model): boolean { + return bool((model.node.layer & REFLECTION_PROBE_DEFAULT_MASK) === model.node.layer || (REFLECTION_PROBE_DEFAULT_MASK & model.visFlags)); +} + const transWorldBounds = new AABB(); function isFrustumVisible (model: Model, frustum: Readonly, castShadow: boolean): boolean { const modelWorldBounds = model.worldBounds; @@ -120,33 +137,94 @@ function isFrustumVisible (model: Model, frustum: Readonly, castShadow: return !intersect.aabbFrustum(transWorldBounds, frustum); } +function isIntersectAABB (lAABB: AABB, rAABB: AABB): boolean { + return !intersect.aabbWithAABB(lAABB, rAABB); +} + +function getReflectMapPassIndex (subModel: SubModel, phaseLayoutId: number): number { + const passes = subModel.passes; + const r = cclegacy.rendering; + for (let k = 0; k < passes.length; k++) { + if ((passes[k].phaseID === phaseLayoutId)) { + return k; + } + } + return -1; +} + +const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; +function applyProbeMacro (model: Model, phaseLayoutId: number): void { + const subModels = model.subModels; + for (let j = 0; j < subModels.length; j++) { + const subModel: SubModel = subModels[j]; + + //Filter transparent objects + const isTransparent = subModel.passes[0].blendState.targets[0].blend; + if (isTransparent) { + continue; + } + + const passIdx = getReflectMapPassIndex(subModel, phaseLayoutId); + let bUseReflectPass = true; + if (passIdx < 0) { + bUseReflectPass = false; + } + + if (!bUseReflectPass) { + let patches: IMacroPatch[] = []; + patches = patches.concat(subModel.patches!); + const useRGBEPatchs: IMacroPatch[] = [ + { name: CC_USE_RGBE_OUTPUT, value: true }, + ]; + patches = patches.concat(useRGBEPatchs); + subModel.onMacroPatchesStateChanged(patches); + } + } +} + function sceneCulling ( - skyboxModelToSkip: Model | null, scene: RenderScene, camera: Camera, camOrLightFrustum: Readonly, castShadow: boolean, + probe: ReflectionProbe | null, + isReflectProbe: boolean, models: Array, + phaseLayoutId: number, ): void { + const skybox = pSceneData.skybox; + const skyboxModel = skybox.model; const visibility = camera.visibility; + const camSkyboxFlag = camera.clearFlag & SKYBOX_FLAG; + if (!castShadow && skybox && skybox.enabled && skyboxModel && camSkyboxFlag) { + models.push(skyboxModel); + } + for (const model of scene.models) { assert(!!model); - if (!model.enabled || model === skyboxModelToSkip || (castShadow && !model.castShadow)) { + if (!model.enabled || !model.node || !model.worldBounds || (castShadow && !model.castShadow)) { continue; } if (scene && scene.isCulledByLod(camera, model)) { continue; } + if (!probe || (probe && probe.probeType === ProbeType.CUBE)) { + if (isNodeVisible(model.node, visibility) + || isModelVisible(model, visibility)) { + // frustum culling + if ((!probe && isFrustumVisible(model, camOrLightFrustum, castShadow)) + || (probe && isIntersectAABB(model.worldBounds, probe.boundingBox!))) { + continue; + } - if (isNodeVisible(model.node, visibility) - || isModelVisible(model, visibility)) { - // frustum culling - if (isFrustumVisible(model, camOrLightFrustum, castShadow)) { - continue; + models.push(model); } - + } else if (isReflectProbeMask(model)) { models.push(model); } + if (probe && isReflectProbe) { + applyProbeMacro(model, phaseLayoutId); + } } } @@ -182,11 +260,16 @@ function addRenderObject ( ): void { const subModels = model.subModels; const subModelCount = subModels.length; + const skyboxModel = pSceneData.skybox.model; for (let subModelIdx = 0; subModelIdx < subModelCount; ++subModelIdx) { const subModel = subModels[subModelIdx]; const passes = subModel.passes; const passCount = passes.length; for (let passIdx = 0; passIdx < passCount; ++passIdx) { + if (model === skyboxModel && !subModelIdx && !passIdx && isDrawOpaqueOrMask) { + queue.opaqueQueue.add(model, computeSortingDepth(camera, model), subModelIdx, passIdx); + continue; + } const pass = passes[passIdx]; // check phase const phaseAllowed = phaseLayoutId === pass.phaseID; @@ -247,9 +330,6 @@ export class SceneCulling { clear (): void { this.resetPool(); this.sceneQueries.clear(); - for (const c of this.culledResults) { - c.length = 0; - } this.culledResults.length = 0; this.renderQueues.length = 0; this.sceneQueryIndex.clear(); @@ -266,27 +346,32 @@ export class SceneCulling { this.fillRenderQueues(rg, pplSceneData); } - private getOrCreateSceneCullingQuery (sceneData: SceneData): number { + private getOrCreateSceneCullingQuery (sceneId: number): number { + const sceneData: SceneData = this.renderGraph.getScene(sceneId); const scene = sceneData.scene!; let queries = this.sceneQueries.get(scene); if (!queries) { this.sceneQueries.set(scene, cullingQueriesRecycle.addWithArgs()); queries = this.sceneQueries.get(scene); } - const castShadow = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); - const key = computeCullingKey(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level); + const castShadow: boolean = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); + const key = computeCullingKey(sceneData, castShadow); const cullNum = queries!.culledResultIndex.get(key); if (cullNum !== undefined) { return cullNum; } - const soureceID = this.numCullingQueries++; + const sourceID = this.numCullingQueries++; if (this.numCullingQueries > this.culledResults.length) { assert(this.numCullingQueries === (this.culledResults.length + 1)); this.culledResults.push([]); } - queries!.culledResultIndex.set(key, soureceID); - queries!.cullingKeyResult.set(key, cullingKeyRecycle.addWithArgs(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level)); - return soureceID; + queries!.culledResultIndex.set(key, sourceID); + queries!.cullingKeyResult.set(key, cullingKeyRecycle.addWithArgs( + sceneData, + castShadow, + sceneId, + )); + return sourceID; } private createRenderQueue (sceneFlags: SceneFlags, subpassOrPassLayoutID: number): number { @@ -312,8 +397,8 @@ export class SceneCulling { assert(!!sceneData.scene); continue; } - const sourceID = this.getOrCreateSceneCullingQuery(sceneData); - const layoutID = getSubpassOrPassID(v, rg, lg); + const sourceID = this.getOrCreateSceneCullingQuery(v); + const layoutID: number = getSubpassOrPassID(v, rg, lg); const targetID = this.createRenderQueue(sceneData.flags, layoutID); const lightType = sceneData.light.light ? sceneData.light.light.type : LightType.UNKNOWN; @@ -331,25 +416,39 @@ export class SceneCulling { } } + private _getPhaseIdFromScene (scene: number): number { + const rg: RenderGraph = this.renderGraph; + const renderQueueId = rg.getParent(scene); + assert(rg.holds(RenderGraphValue.Queue, renderQueueId)); + const graphRenderQueue = rg.getQueue(renderQueueId); + return graphRenderQueue.phaseID; + } + private batchCulling (pplSceneData: PipelineSceneData): void { - const skybox = pplSceneData.skybox; - const skyboxModelToSkip = skybox ? skybox.model : null; for (const [scene, queries] of this.sceneQueries) { assert(!!scene); for (const [key, sourceID] of queries.culledResultIndex) { const cullingKey = queries.cullingKeyResult.get(key)!; - assert(!!cullingKey.camera); - assert(cullingKey.camera.scene === scene); - const camera = cullingKey.camera; - const light = cullingKey.light; - const level = cullingKey.lightLevel; + const sceneData = cullingKey.sceneData; + assert(!!sceneData.camera); + assert(sceneData.camera.scene === scene); + const camera = sceneData.camera; + const light = sceneData.light.light; + const level = sceneData.light.level; const castShadow = cullingKey.castShadows; + const reflectProbe = sceneData.light.probe; assert(sourceID < this.culledResults.length); const models = this.culledResults[sourceID]; + const isReflectProbe = bool(sceneData.flags & SceneFlags.REFLECTION_PROBE); + const phaseId = this._getPhaseIdFromScene(cullingKey.sceneId); + if (reflectProbe) { + sceneCulling(scene, reflectProbe.camera, reflectProbe.camera.frustum, castShadow, reflectProbe, isReflectProbe, models, phaseId); + continue; + } if (light) { switch (light.type) { case LightType.SPOT: - sceneCulling(skyboxModelToSkip, scene, camera, (light as SpotLight).frustum, castShadow, models); + sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, null, isReflectProbe, models, phaseId); break; case LightType.DIRECTIONAL: { const csmLayers = pplSceneData.csmLayers; @@ -371,28 +470,27 @@ export class SceneCulling { frustum = csmLayers.layers[level].validFrustum; } } - sceneCulling(skyboxModelToSkip, scene, camera, frustum, castShadow, models); + sceneCulling(scene, camera, frustum, castShadow, null, isReflectProbe, models, phaseId); } break; default: } } else { - sceneCulling(skyboxModelToSkip, scene, camera, camera.frustum, castShadow, models); + sceneCulling(scene, camera, camera.frustum, castShadow, null, isReflectProbe, models, phaseId); } } } } private fillRenderQueues (rg: RenderGraph, pplSceneData: PipelineSceneData): void { - const skybox = pplSceneData.skybox; for (const [sceneId, desc] of this.sceneQueryIndex) { assert(rg.holds(RenderGraphValue.Scene, sceneId)); const sourceId = desc.culledSource; const targetId = desc.renderQueueTarget; const sceneData = rg.getScene(sceneId); - const isDrawBlend = bool(sceneData.flags & SceneFlags.TRANSPARENT_OBJECT); - const isDrawOpaqueOrMask = bool(sceneData.flags & (SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT)); - const isDrawShadowCaster = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); + const isDrawBlend: boolean = bool(sceneData.flags & SceneFlags.TRANSPARENT_OBJECT); + const isDrawOpaqueOrMask: boolean = bool(sceneData.flags & (SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT)); + const isDrawShadowCaster: boolean = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); if (!isDrawShadowCaster && !isDrawBlend && !isDrawOpaqueOrMask) { continue; } @@ -415,22 +513,6 @@ export class SceneCulling { // skybox const camera = sceneData.camera; assert(!!camera); - if (!bool(sceneData.flags & SceneFlags.SHADOW_CASTER) - && skybox && skybox.enabled - && (camera.clearFlag & SKYBOX_FLAG)) { - assert(!!skybox.model); - const model = skybox.model; - const node = model.node; - let depth = 0; - if (node) { - const tempVec3 = vec3Pool.acquire(); - Vec3.subtract(tempVec3, node.worldPosition, camera.position); - depth = tempVec3.dot(camera.forward); - vec3Pool.release(tempVec3); - } - renderQueue.opaqueQueue.add(model, depth, 0, 0); - } - // fill render queue for (const model of sourceModels) { addRenderObject( diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index f65f0eefe9a..312dda5e096 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -29,7 +29,7 @@ */ /* eslint-disable max-len */ import { ResolveMode, ShaderStageFlagBit, Type, UniformBlock } from '../../gfx'; -import { Light } from '../../render-scene/scene'; +import { Light, ReflectionProbe } from '../../render-scene/scene'; import { OutputArchive, InputArchive } from './archive'; import { saveUniformBlock, loadUniformBlock } from './serialization'; import { RecyclePool } from '../../core/memop'; @@ -289,17 +289,20 @@ export function getClearValueTypeName (e: ClearValueType): string { } export class LightInfo { - constructor (light: Light | null = null, level = 0, culledByLight = false) { + constructor (light: Light | null = null, level = 0, culledByLight = false, probe: ReflectionProbe | null = null) { this.light = light; this.level = level; this.culledByLight = culledByLight; + this.probe = probe; } - reset (light: Light | null = null, level = 0, culledByLight = false): void { + reset (light: Light | null = null, level = 0, culledByLight = false, probe: ReflectionProbe | null = null): void { this.light = light; this.level = level; this.culledByLight = culledByLight; + this.probe = probe; } /*refcount*/ light: Light | null; + probe: ReflectionProbe | null; level: number; culledByLight: boolean; } diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 753aba5701d..80e2d467a2c 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -1,5 +1,6 @@ import { RecyclePool, UpdateRecyclePool } from '../../core'; import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; +import { IMacroPatch } from '../../render-scene'; import { LightType, Model, SubModel } from '../../render-scene/scene'; import { SetIndex } from '../define'; import { InstancedBuffer } from '../instanced-buffer'; @@ -125,6 +126,23 @@ export class RenderDrawQueue { cmdBuffer.draw(inputAssembler); } } + + removeMacro (macroName: string): void { + for (const instance of this.instances) { + const subModel = instance.subModel!; + let patches: IMacroPatch[] = []; + patches = patches.concat(subModel.patches!); + if (!patches.length) continue; + for (let j = 0; j < patches.length; j++) { + const patch = patches[j]; + if (patch.name === macroName) { + patches.splice(j, 1); + break; + } + } + subModel.onMacroPatchesStateChanged(patches); + } + } } export class RenderInstancingQueue { From b4f3ebce16e657cba0386d4879ac889abcd7f965 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 17 Aug 2023 16:41:00 +0800 Subject: [PATCH 29/82] [Completed] the logic adjustment for reflection probes --- cocos/rendering/custom/define.ts | 6 +- cocos/rendering/custom/executor.ts | 5 +- cocos/rendering/custom/scene-culling.ts | 68 ++++----------- cocos/rendering/custom/web-pipeline-types.ts | 87 ++++++++++++++++---- 4 files changed, 88 insertions(+), 78 deletions(-) diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index 54300dc05dc..b0898db37bb 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -755,8 +755,10 @@ export function buildReflectionProbePass ( probeCamera.clearStencil, probeCamera.clearFlag, ); - const passBuilder = probePass.addQueue(QueueHint.RENDER_OPAQUE); - passBuilder.addSceneOfCamera(camera, new LightInfo(), SceneFlags.REFLECTION_PROBE); + const passBuilder = probePass.addQueue(QueueHint.RENDER_OPAQUE, 'reflect-map'); + const lightInfo = new LightInfo(); + lightInfo.probe = probe; + passBuilder.addSceneOfCamera(camera, lightInfo, SceneFlags.REFLECTION_PROBE | SceneFlags.OPAQUE_OBJECT); updateCameraUBO(passBuilder as unknown as any, probeCamera, ppl); } diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 477b1a92f8e..d24bae10b85 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1118,7 +1118,6 @@ class DevicePreSceneTask extends WebSceneTask { // this._uploadInstanceBuffers(); } } -const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; const sceneViewport = new Viewport(); class DeviceSceneTask extends WebSceneTask { protected _currentQueue: DeviceRenderQueue; @@ -1290,9 +1289,7 @@ class DeviceSceneTask extends WebSceneTask { renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); - if (!bool(graphSceneData.flags & SceneFlags.REFLECTION_PROBE) && graphSceneData.light.probe) { - renderQueue.opaqueQueue.removeMacro(CC_USE_RGBE_OUTPUT); - } + if (bool(graphSceneData.flags & SceneFlags.REFLECTION_PROBE)) renderQueue.probeQueue.removeMacro(); if (graphSceneData.flags & SceneFlags.GEOMETRY) { this.camera!.geometryRenderer?.render( devicePass.renderPass, diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index e20a6b5bbda..19dee8ba62f 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -85,17 +85,14 @@ function computeCullingKey ( class CullingKey extends UpdateRecyclePool { sceneData: SceneData; castShadows = false; - sceneId = -1; constructor (sceneData: SceneData, castShadows: boolean, verId: number) { super(); this.sceneData = sceneData; this.castShadows = castShadows; - this.sceneId = verId; } update (sceneData: SceneData, castShadows: boolean, verId: number): void { this.sceneData = sceneData; this.castShadows = castShadows; - this.sceneId = verId; } } @@ -141,47 +138,6 @@ function isIntersectAABB (lAABB: AABB, rAABB: AABB): boolean { return !intersect.aabbWithAABB(lAABB, rAABB); } -function getReflectMapPassIndex (subModel: SubModel, phaseLayoutId: number): number { - const passes = subModel.passes; - const r = cclegacy.rendering; - for (let k = 0; k < passes.length; k++) { - if ((passes[k].phaseID === phaseLayoutId)) { - return k; - } - } - return -1; -} - -const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; -function applyProbeMacro (model: Model, phaseLayoutId: number): void { - const subModels = model.subModels; - for (let j = 0; j < subModels.length; j++) { - const subModel: SubModel = subModels[j]; - - //Filter transparent objects - const isTransparent = subModel.passes[0].blendState.targets[0].blend; - if (isTransparent) { - continue; - } - - const passIdx = getReflectMapPassIndex(subModel, phaseLayoutId); - let bUseReflectPass = true; - if (passIdx < 0) { - bUseReflectPass = false; - } - - if (!bUseReflectPass) { - let patches: IMacroPatch[] = []; - patches = patches.concat(subModel.patches!); - const useRGBEPatchs: IMacroPatch[] = [ - { name: CC_USE_RGBE_OUTPUT, value: true }, - ]; - patches = patches.concat(useRGBEPatchs); - subModel.onMacroPatchesStateChanged(patches); - } - } -} - function sceneCulling ( scene: RenderScene, camera: Camera, @@ -190,7 +146,6 @@ function sceneCulling ( probe: ReflectionProbe | null, isReflectProbe: boolean, models: Array, - phaseLayoutId: number, ): void { const skybox = pSceneData.skybox; const skyboxModel = skybox.model; @@ -222,9 +177,6 @@ function sceneCulling ( } else if (isReflectProbeMask(model)) { models.push(model); } - if (probe && isReflectProbe) { - applyProbeMacro(model, phaseLayoutId); - } } } @@ -254,10 +206,15 @@ function addRenderObject ( phaseLayoutId: number, isDrawOpaqueOrMask: boolean, isDrawBlend: boolean, + isDrawProbe: boolean, camera: Camera, model: Model, queue: RenderQueue, ): void { + const probeQueue = queue.probeQueue; + if (isDrawProbe) { + probeQueue.applyMacro(model, phaseLayoutId); + } const subModels = model.subModels; const subModelCount = subModels.length; const skyboxModel = pSceneData.skybox.model; @@ -265,6 +222,8 @@ function addRenderObject ( const subModel = subModels[subModelIdx]; const passes = subModel.passes; const passCount = passes.length; + const probePhase = probeQueue.probeMap.get(subModel); + if (probePhase !== undefined) phaseLayoutId = probePhase; for (let passIdx = 0; passIdx < passCount; ++passIdx) { if (model === skyboxModel && !subModelIdx && !passIdx && isDrawOpaqueOrMask) { queue.opaqueQueue.add(model, computeSortingDepth(camera, model), subModelIdx, passIdx); @@ -440,15 +399,14 @@ export class SceneCulling { assert(sourceID < this.culledResults.length); const models = this.culledResults[sourceID]; const isReflectProbe = bool(sceneData.flags & SceneFlags.REFLECTION_PROBE); - const phaseId = this._getPhaseIdFromScene(cullingKey.sceneId); if (reflectProbe) { - sceneCulling(scene, reflectProbe.camera, reflectProbe.camera.frustum, castShadow, reflectProbe, isReflectProbe, models, phaseId); + sceneCulling(scene, reflectProbe.camera, reflectProbe.camera.frustum, castShadow, reflectProbe, isReflectProbe, models); continue; } if (light) { switch (light.type) { case LightType.SPOT: - sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, null, isReflectProbe, models, phaseId); + sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, null, isReflectProbe, models); break; case LightType.DIRECTIONAL: { const csmLayers = pplSceneData.csmLayers; @@ -470,13 +428,13 @@ export class SceneCulling { frustum = csmLayers.layers[level].validFrustum; } } - sceneCulling(scene, camera, frustum, castShadow, null, isReflectProbe, models, phaseId); + sceneCulling(scene, camera, frustum, castShadow, null, isReflectProbe, models); } break; default: } } else { - sceneCulling(scene, camera, camera.frustum, castShadow, null, isReflectProbe, models, phaseId); + sceneCulling(scene, camera, camera.frustum, castShadow, null, isReflectProbe, models); } } } @@ -491,7 +449,8 @@ export class SceneCulling { const isDrawBlend: boolean = bool(sceneData.flags & SceneFlags.TRANSPARENT_OBJECT); const isDrawOpaqueOrMask: boolean = bool(sceneData.flags & (SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT)); const isDrawShadowCaster: boolean = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); - if (!isDrawShadowCaster && !isDrawBlend && !isDrawOpaqueOrMask) { + const isDrawProbe: boolean = bool(sceneData.flags & SceneFlags.REFLECTION_PROBE); + if (!isDrawShadowCaster && !isDrawBlend && !isDrawOpaqueOrMask && !isDrawProbe) { continue; } // render queue info @@ -519,6 +478,7 @@ export class SceneCulling { phaseLayoutId, isDrawOpaqueOrMask, isDrawBlend, + isDrawProbe, camera, model, renderQueue, diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 80e2d467a2c..3a3215954d1 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -1,4 +1,4 @@ -import { RecyclePool, UpdateRecyclePool } from '../../core'; +import { RecyclePool, UpdateRecyclePool, cclegacy } from '../../core'; import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; import { IMacroPatch } from '../../render-scene'; import { LightType, Model, SubModel } from '../../render-scene/scene'; @@ -57,6 +57,72 @@ export const instancePool = new RecyclePool(( passIndex: number = 0, ) => new DrawInstance(subModel, priority, hash, depth, shaderID, passIndex), 0); +const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; +function getLayoutId (passLayout: string, phaseLayout: string): number { + const r = cclegacy.rendering; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return r.getPhaseID(r.getPassID(passLayout), phaseLayout); +} +function getPassIndexFromLayout (subModel: SubModel, phaseLayoutId: number): number { + const passes = subModel.passes; + for (let k = 0; k < passes.length; k++) { + if ((passes[k].phaseID === phaseLayoutId)) { + return k; + } + } + return -1; +} + +export class ProbeHelperQueue { + probeMap: Map = new Map(); + removeMacro (): void { + for (const [subModel] of this.probeMap) { + let patches: IMacroPatch[] = []; + patches = patches.concat(subModel.patches!); + if (!patches.length) continue; + for (let j = 0; j < patches.length; j++) { + const patch = patches[j]; + if (patch.name === CC_USE_RGBE_OUTPUT) { + patches.splice(j, 1); + break; + } + } + subModel.onMacroPatchesStateChanged(patches); + } + } + applyMacro (model: Model, probeLayoutId: number): void { + const subModels = model.subModels; + for (let j = 0; j < subModels.length; j++) { + const subModel: SubModel = subModels[j]; + + //Filter transparent objects + const isTransparent = subModel.passes[0].blendState.targets[0].blend; + if (isTransparent) { + continue; + } + + let passIdx = getPassIndexFromLayout(subModel, probeLayoutId); + let bUseReflectPass = true; + if (passIdx < 0) { + probeLayoutId = getLayoutId('default', 'default'); + passIdx = getPassIndexFromLayout(subModel, probeLayoutId); + bUseReflectPass = false; + } + if (passIdx < 0) { continue; } + if (!bUseReflectPass) { + let patches: IMacroPatch[] = []; + patches = patches.concat(subModel.patches!); + const useRGBEPatchs: IMacroPatch[] = [ + { name: CC_USE_RGBE_OUTPUT, value: true }, + ]; + patches = patches.concat(useRGBEPatchs); + subModel.onMacroPatchesStateChanged(patches); + } + this.probeMap.set(subModel, probeLayoutId); + } + } +} + export class RenderDrawQueue { instances: Array = new Array(); @@ -126,23 +192,6 @@ export class RenderDrawQueue { cmdBuffer.draw(inputAssembler); } } - - removeMacro (macroName: string): void { - for (const instance of this.instances) { - const subModel = instance.subModel!; - let patches: IMacroPatch[] = []; - patches = patches.concat(subModel.patches!); - if (!patches.length) continue; - for (let j = 0; j < patches.length; j++) { - const patch = patches[j]; - if (patch.name === macroName) { - patches.splice(j, 1); - break; - } - } - subModel.onMacroPatchesStateChanged(patches); - } - } } export class RenderInstancingQueue { @@ -242,6 +291,7 @@ export class RenderQueueDesc extends UpdateRecyclePool { } export class RenderQueue extends UpdateRecyclePool { + probeQueue: ProbeHelperQueue = new ProbeHelperQueue(); opaqueQueue: RenderDrawQueue = new RenderDrawQueue(); transparentQueue: RenderDrawQueue = new RenderDrawQueue(); opaqueInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); @@ -266,6 +316,7 @@ export class RenderQueue extends UpdateRecyclePool { } update (): void { + this.probeQueue.probeMap.clear(); this.opaqueQueue.instances.length = 0; this.transparentQueue.instances.length = 0; this._clearInstances(this.opaqueInstancingQueue.batches); From 4af68a8329e61a87ee0ca997415a2c0d35c87453 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 17 Aug 2023 17:42:11 +0800 Subject: [PATCH 30/82] [Update] --- cocos/rendering/custom/scene-culling.ts | 4 ++-- cocos/rendering/custom/web-pipeline-types.ts | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 19dee8ba62f..3753430b403 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -222,8 +222,8 @@ function addRenderObject ( const subModel = subModels[subModelIdx]; const passes = subModel.passes; const passCount = passes.length; - const probePhase = probeQueue.probeMap.get(subModel); - if (probePhase !== undefined) phaseLayoutId = probePhase; + const probePhase = probeQueue.probeMap.includes(subModel); + if (probePhase) phaseLayoutId = probeQueue.defaultId; for (let passIdx = 0; passIdx < passCount; ++passIdx) { if (model === skyboxModel && !subModelIdx && !passIdx && isDrawOpaqueOrMask) { queue.opaqueQueue.add(model, computeSortingDepth(camera, model), subModelIdx, passIdx); diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 3a3215954d1..dd8fb863361 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -74,9 +74,10 @@ function getPassIndexFromLayout (subModel: SubModel, phaseLayoutId: number): num } export class ProbeHelperQueue { - probeMap: Map = new Map(); + probeMap: Array = new Array(); + defaultId: number = getLayoutId('default', 'default'); removeMacro (): void { - for (const [subModel] of this.probeMap) { + for (const subModel of this.probeMap) { let patches: IMacroPatch[] = []; patches = patches.concat(subModel.patches!); if (!patches.length) continue; @@ -104,7 +105,7 @@ export class ProbeHelperQueue { let passIdx = getPassIndexFromLayout(subModel, probeLayoutId); let bUseReflectPass = true; if (passIdx < 0) { - probeLayoutId = getLayoutId('default', 'default'); + probeLayoutId = this.defaultId; passIdx = getPassIndexFromLayout(subModel, probeLayoutId); bUseReflectPass = false; } @@ -117,8 +118,8 @@ export class ProbeHelperQueue { ]; patches = patches.concat(useRGBEPatchs); subModel.onMacroPatchesStateChanged(patches); + this.probeMap.push(subModel); } - this.probeMap.set(subModel, probeLayoutId); } } } @@ -316,7 +317,7 @@ export class RenderQueue extends UpdateRecyclePool { } update (): void { - this.probeQueue.probeMap.clear(); + this.probeQueue.probeMap.length = 0; this.opaqueQueue.instances.length = 0; this.transparentQueue.instances.length = 0; this._clearInstances(this.opaqueInstancingQueue.batches); From 6d5125a2fb40dcbf0b001e2246c58e3b2fb74e66 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 17 Aug 2023 18:54:16 +0800 Subject: [PATCH 31/82] remove view type from subresource view --- cocos/rendering/custom/pipeline.ts | 33 ++++++++++--------- cocos/rendering/custom/render-graph.ts | 3 +- .../pipeline/custom/FrameGraphDispatcher.cpp | 6 ++-- .../pipeline/custom/NativePipelineTypes.h | 8 ++--- .../pipeline/custom/NativeResourceGraph.cpp | 7 ++-- .../pipeline/custom/RenderGraphTypes.h | 1 - 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 9635183715e..d40be0f00fc 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -684,19 +684,9 @@ export interface BasicPipeline extends PipelineRuntime { width: number, height: number, format?: Format): void; - addBuffer ( - name: string, - size: number, - flags: ResourceFlags, - residency: ResourceResidency): number; - updateBuffer ( - name: string, - size: number): void; - addExternalTexture (name: string, texture: Texture, flags: ResourceFlags): number; - updateExternalTexture (name: string, texture: Texture): void; - addTexture ( + addResource ( name: string, - textureType: TextureType, + dimension: ResourceDimension, format: Format, width: number, height: number, @@ -706,7 +696,7 @@ export interface BasicPipeline extends PipelineRuntime { sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number; - updateTexture ( + updateResource ( name: string, format: Format, width: number, @@ -715,9 +705,9 @@ export interface BasicPipeline extends PipelineRuntime { arraySize: number, mipLevels: number, sampleCount: SampleCount): void; - addResource ( + addTexture ( name: string, - dimension: ResourceDimension, + type: TextureType, format: Format, width: number, height: number, @@ -727,7 +717,7 @@ export interface BasicPipeline extends PipelineRuntime { sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number; - updateResource ( + updateTexture ( name: string, format: Format, width: number, @@ -736,6 +726,17 @@ export interface BasicPipeline extends PipelineRuntime { arraySize: number, mipLevels: number, sampleCount: SampleCount): void; + addBuffer ( + name: string, + size: number, + flags: ResourceFlags, + residency: ResourceResidency): number; + updateBuffer (name: string, size: number): void; + addExternalTexture ( + name: string, + texture: Texture, + flags: ResourceFlags): number; + updateExternalTexture (name: string, texture: Texture): void; /** * @engineInternal * @en Begin rendering one frame diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 6a24501ea02..eafbb37186f 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -31,7 +31,7 @@ import { AdjI, AdjacencyGraph, BidirectionalGraph, ComponentGraph, ED, InEI, MutableGraph, MutableReferenceGraph, NamedGraph, OutE, OutEI, PolymorphicGraph, PropertyGraph, PropertyMap, ReferenceGraph, UuidGraph, VertexListGraph, directional, parallel, reindexEdgeList, traversal } from './graph'; import { Material } from '../../asset/assets'; import { Camera } from '../../render-scene/scene/camera'; -import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp, RenderPass, SampleCount, Sampler, SamplerInfo, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureFlagBit, Viewport, TextureType } from '../../gfx'; +import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp, RenderPass, SampleCount, Sampler, SamplerInfo, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureFlagBit, TextureType, Viewport } from '../../gfx'; import { AccessType, AttachmentType, ClearValueType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UploadPair, RenderCommonObjectPool } from './types'; import { RenderScene } from '../../render-scene/core/render-scene'; import { RenderWindow } from '../../render-scene/core/render-window'; @@ -160,6 +160,7 @@ export class ResourceDesc { this.sampleCount = SampleCount.X1; this.textureFlags = TextureFlagBit.NONE; this.flags = ResourceFlags.NONE; + this.viewType = TextureType.TEX2D; } dimension: ResourceDimension = ResourceDimension.BUFFER; alignment = 0; diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index e6087402ac8..90f8c3acdc5 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -1533,7 +1533,7 @@ gfx::SamplerInfo makePointSamplerInfo() { return gfx::SamplerInfo{gfx::Filter::POINT, gfx::Filter::POINT, gfx::Filter::POINT}; } -SubresourceView makeSubresourceView(const ResourceDesc& srcDesc, const ResourceDesc &targetDesc, const gfx::ResourceRange& range) { +SubresourceView makeSubresourceView(const ResourceDesc &targetDesc, const gfx::ResourceRange& range) { SubresourceView view{}; view.firstArraySlice = range.firstSlice; view.numArraySlices = range.numSlices; @@ -1542,7 +1542,6 @@ SubresourceView makeSubresourceView(const ResourceDesc& srcDesc, const ResourceD view.firstPlane = range.basePlane; view.numPlanes = range.planeCount; view.format = targetDesc.format; - view.viewType = srcDesc.viewType; view.textureView = nullptr; return view; } @@ -1659,7 +1658,6 @@ void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) { auto descResViewID = findVertex(subres, resg); auto targetResID = rag.resourceIndex.at(resName); - const auto &srcDesc = get(ResourceGraph::DescTag{}, resg, descResViewID); const auto &targetName = get(ResourceGraph::NameTag{}, resg, targetResID); const auto &targetDesc = get(ResourceGraph::DescTag{}, resg, targetResID); const auto &srcResourceRange = rag.movedSourceStatus.at(subres).range; @@ -1667,7 +1665,7 @@ void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) { const auto &indexName = concatResName(targetName, subres, rag.resource()); auto subresID = findVertex(indexName, resg); if (subresID == ResourceGraph::null_vertex()) { - const auto &subView = makeSubresourceView(srcDesc, targetDesc, srcResourceRange); + const auto &subView = makeSubresourceView(targetDesc, srcResourceRange); // register to resourcegraph subresID = addVertex( SubresourceViewTag{}, diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 2f5704b28f8..8d24abdb9cc 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1357,20 +1357,20 @@ class NativePipeline final : public Pipeline { void beginSetup() override; void endSetup() override; bool containsResource(const ccstd::string &name) const override; - uint32_t addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) override; - void updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) override; uint32_t addRenderWindow(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, scene::RenderWindow *renderWindow) override; void updateRenderWindow(const ccstd::string &name, scene::RenderWindow *renderWindow) override; uint32_t addRenderTarget(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, ResourceResidency residency) override; uint32_t addDepthStencil(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, ResourceResidency residency) override; void updateRenderTarget(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) override; void updateDepthStencil(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) override; + uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; + void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; uint32_t addBuffer(const ccstd::string &name, uint32_t size, ResourceFlags flags, ResourceResidency residency) override; void updateBuffer(const ccstd::string &name, uint32_t size) override; - uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; - void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; + uint32_t addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) override; + void updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) override; void beginFrame() override; void update(const scene::Camera *camera) override; void endFrame() override; diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 750616d549a..604a9aca1fa 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -143,12 +143,12 @@ gfx::TextureInfo getTextureInfo(const ResourceDesc& desc) { }; } -gfx::TextureViewInfo getTextureViewInfo(const SubresourceView& subresView) { +gfx::TextureViewInfo getTextureViewInfo(const SubresourceView& subresView, gfx::TextureType viewType) { using namespace gfx; // NOLINT(google-build-using-namespace) return { nullptr, - subresView.viewType, + viewType, subresView.format, subresView.indexOrFirstMipLevel, subresView.numMipLevels, @@ -252,7 +252,8 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { mount(device, parentID); // NOLINT(misc-no-recursion) auto* parentTexture = resg.getTexture(parentID); if (!view.textureView) { - auto textureViewInfo = getTextureViewInfo(originView); + const auto& desc = get(ResourceGraph::DescTag{}, resg, vertID); + auto textureViewInfo = getTextureViewInfo(originView, desc.viewType); textureViewInfo.texture = parentTexture; view.textureView = device->createTexture(textureViewInfo); } diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h index 4052db29e18..2ab46b7bdab 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h @@ -518,7 +518,6 @@ struct SubresourceView { uint16_t numArraySlices{0}; uint16_t firstPlane{0}; uint16_t numPlanes{0}; - gfx::TextureType viewType; }; struct ResourceGraph { From 0c3e5946f341905d069c0d9d0237b543dce29cdc Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 23 Aug 2023 15:42:02 +0800 Subject: [PATCH 32/82] add reflection probe --- cocos/rendering/custom/types.ts | 14 +++++++++----- .../renderer/pipeline/custom/RenderCommonJsb.cpp | 7 +++++++ .../pipeline/custom/RenderCommonSerialization.h | 2 ++ .../renderer/pipeline/custom/RenderCommonTypes.h | 14 +++++++++++++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 0d8eadb3722..47ff74a394c 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -29,7 +29,8 @@ */ /* eslint-disable max-len */ import { ResolveMode, ShaderStageFlagBit, Type, UniformBlock } from '../../gfx'; -import { Light, ReflectionProbe } from '../../render-scene/scene'; +import { ReflectionProbe } from '../../render-scene/scene/reflection-probe'; +import { Light } from '../../render-scene/scene'; import { OutputArchive, InputArchive } from './archive'; import { saveUniformBlock, loadUniformBlock } from './serialization'; import { RecyclePool } from '../../core/memop'; @@ -291,18 +292,18 @@ export function getClearValueTypeName (e: ClearValueType): string { export class LightInfo { constructor (light: Light | null = null, level = 0, culledByLight = false, probe: ReflectionProbe | null = null) { this.light = light; + this.probe = probe; this.level = level; this.culledByLight = culledByLight; - this.probe = probe; } reset (light: Light | null = null, level = 0, culledByLight = false, probe: ReflectionProbe | null = null): void { this.light = light; + this.probe = probe; this.level = level; this.culledByLight = culledByLight; - this.probe = probe; } /*refcount*/ light: Light | null; - probe: ReflectionProbe | null; + /*pointer*/ probe: ReflectionProbe | null; level: number; culledByLight: boolean; } @@ -667,9 +668,10 @@ export class RenderCommonObjectPool { light: Light | null = null, level = 0, culledByLight = false, + probe: ReflectionProbe | null = null, ): LightInfo { const v = this._lightInfo.add(); - v.reset(light, level, culledByLight); + v.reset(light, level, culledByLight, probe); return v; } createDescriptor ( @@ -773,12 +775,14 @@ export class RenderCommonObjectPool { export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { // skip, v.light: Light + // skip, v.probe: ReflectionProbe ar.writeNumber(v.level); ar.writeBool(v.culledByLight); } export function loadLightInfo (ar: InputArchive, v: LightInfo): void { // skip, v.light: Light + // skip, v.probe: ReflectionProbe v.level = ar.readNumber(); v.culledByLight = ar.readBool(); } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp index c7fed6ceedb..249ddbbd78c 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp @@ -41,6 +41,9 @@ bool nativevalue_to_se(const cc::render::LightInfo &from, se::Value &to, se::Obj nativevalue_to_se(from.light, tmp, ctx); obj->setProperty("light", tmp); + nativevalue_to_se(from.probe, tmp, ctx); + obj->setProperty("probe", tmp); + nativevalue_to_se(from.level, tmp, ctx); obj->setProperty("level", tmp); @@ -241,6 +244,10 @@ bool sevalue_to_native(const se::Value &from, cc::render: if(!field.isNullOrUndefined()) { ok &= sevalue_to_native(field, &(to->light), ctx); } + obj->getProperty("probe", &field, true); + if(!field.isNullOrUndefined()) { + ok &= sevalue_to_native(field, &(to->probe), ctx); + } obj->getProperty("level", &field, true); if(!field.isNullOrUndefined()) { ok &= sevalue_to_native(field, &(to->level), ctx); diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h index 4c9467badf2..913dbab6af1 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h @@ -39,12 +39,14 @@ namespace render { inline void save(OutputArchive& ar, const LightInfo& v) { // skip, light: IntrusivePtr + // skip, probe: scene::ReflectionProbe save(ar, v.level); save(ar, v.culledByLight); } inline void load(InputArchive& ar, LightInfo& v) { // skip, light: IntrusivePtr + // skip, probe: scene::ReflectionProbe load(ar, v.level); load(ar, v.culledByLight); } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index cad5d71c02c..2054c2d314e 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -39,6 +39,16 @@ namespace cc { +namespace scene { + +class ReflectionProbe; + +} // namespace scene + +} // namespace cc + +namespace cc { + namespace render { enum class UpdateFrequency { @@ -211,8 +221,9 @@ enum class ClearValueType { struct LightInfo { LightInfo() = default; - LightInfo(IntrusivePtr lightIn, uint32_t levelIn, bool culledByLightIn) noexcept + LightInfo(IntrusivePtr lightIn, uint32_t levelIn, bool culledByLightIn, scene::ReflectionProbe* probeIn) noexcept : light(std::move(lightIn)), + probe(probeIn), level(levelIn), culledByLight(culledByLightIn) {} LightInfo(IntrusivePtr lightIn, uint32_t levelIn) noexcept @@ -220,6 +231,7 @@ struct LightInfo { level(levelIn) {} IntrusivePtr light; + scene::ReflectionProbe* probe{nullptr}; uint32_t level{0}; bool culledByLight{false}; }; From 2a1931ae3e954134ea6a3e70e871722da8f53afc Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 25 Aug 2023 11:05:01 +0800 Subject: [PATCH 33/82] [Modify] Native reflectionProbe --- .../pipeline/custom/NativePipelineTypes.cpp | 61 ++++++++ .../pipeline/custom/NativePipelineTypes.h | 17 +++ .../pipeline/custom/NativeSceneCulling.cpp | 139 ++++++++++-------- .../pipeline/custom/RenderCommonJsb.cpp | 3 + .../pipeline/custom/RenderCommonTypes.h | 8 +- 5 files changed, 165 insertions(+), 63 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index d8de417ef46..13402865da4 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -224,6 +224,67 @@ PipelineCustomization::PipelineCustomization(PipelineCustomization const& rhs, c renderQueues(rhs.renderQueues, alloc), renderCommands(rhs.renderCommands, alloc) {} +void ProbeHelperQueue::removeMacro() +{ + for (auto subModel : probeMap) { + std::vector patches; + patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); + + for (size_t j = 0; j < patches.size(); ++j) { + const cc::scene::IMacroPatch& patch = patches[j]; + if (patch.name == "CC_USE_RGBE_OUTPUT") { + patches.erase(patches.begin() + j); + break; + } + } + + subModel->onMacroPatchesStateChanged(patches); + } +} + +int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) + { + const auto& passes = subModel->getPasses(); + for (size_t k = 0; k < passes->size(); ++k) { + if (passes->at(k)->getPhaseID() == phaseLayoutId) { + return static_cast(k); + } + } + return -1; +} + +void ProbeHelperQueue::applyMacro(const LayoutGraphData & lg, const cc::scene::Model & model, int probeLayoutId) +{ + const std::vector>& subModels = model.getSubModels(); + for (size_t j = 0; j < subModels.size(); ++j) { + const cc::IntrusivePtr& subModel = subModels[j]; + + const bool isTransparent = subModel->getPasses()->at(0)->getBlendState()->targets[0].blend; + if (isTransparent) { + continue; + } + + int passIdx = getPassIndexFromLayout(subModel, probeLayoutId); + bool bUseReflectPass = true; + if (passIdx < 0) { + probeLayoutId = getDefaultId(lg); + passIdx = getPassIndexFromLayout(subModel, probeLayoutId); + bUseReflectPass = false; + } + if (passIdx < 0) { + continue; + } + if (!bUseReflectPass) { + std::vector patches; + patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); + const cc::scene::IMacroPatch useRGBEPatch = {"CC_USE_RGBE_OUTPUT", true}; + patches.push_back(useRGBEPatch); + subModel->onMacroPatchesStateChanged(patches); + probeMap.push_back(subModel); + } + } + } + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 8d24abdb9cc..9780cc9615f 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -41,6 +41,7 @@ #include "cocos/renderer/pipeline/custom/NativeTypes.h" #include "cocos/renderer/pipeline/custom/details/Map.h" #include "cocos/renderer/pipeline/custom/details/Set.h" +#include "LayoutGraphGraphs.h" #ifdef _MSC_VER #pragma warning(push) @@ -930,6 +931,20 @@ struct DrawInstance { uint32_t passIndex{0}; }; +struct ProbeHelperQueue { + std::vector probeMap; + + int getDefaultId(const LayoutGraphData &lg) { + return locate(locate(LayoutGraphData::null_vertex(), "default", lg), "default", lg); + } + + void removeMacro(); + + int getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId); + + void applyMacro(const LayoutGraphData &lg, const cc::scene::Model& model, int probeLayoutId); +}; + struct RenderDrawQueue { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT @@ -976,6 +991,7 @@ struct NativeRenderQueue { RenderDrawQueue opaqueQueue; RenderDrawQueue transparentQueue; + ProbeHelperQueue probeQueue; RenderInstancingQueue opaqueInstancingQueue; RenderInstancingQueue transparentInstancingQueue; SceneFlags sceneFlags{SceneFlags::NONE}; @@ -1149,6 +1165,7 @@ struct SceneResource { struct CullingKey { const scene::Camera* camera{nullptr}; const scene::Light* light{nullptr}; + const scene::ReflectionProbe* probe{nullptr}; bool castShadow{false}; uint32_t lightLevel{0xFFFFFFFF}; }; diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 0b9a2865259..aaf808a6329 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -6,11 +6,12 @@ #include "cocos/scene/RenderScene.h" #include "cocos/scene/Skybox.h" #include "cocos/scene/SpotLight.h" +#include "cocos/renderer/pipeline/Define.h" namespace cc { namespace render { - +const static uint32_t REFLECTION_PROBE_DEFAULT_MASK = ~static_cast(pipeline::LayerList::UI_2D) & ~static_cast(pipeline::LayerList::PROFILER) & ~static_cast(pipeline::LayerList::UI_3D) & ~static_cast(pipeline::LayerList::GIZMOS) & ~static_cast(pipeline::LayerList::SCENE_GIZMO) & ~static_cast(pipeline::LayerList::EDITOR); void NativeRenderQueue::clear() noexcept { opaqueQueue.instances.clear(); transparentQueue.instances.clear(); @@ -40,6 +41,7 @@ uint32_t SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sceneData) const auto key = CullingKey{ sceneData.camera, sceneData.light.light, + sceneData.light.probe, bCastShadow, sceneData.light.level, }; @@ -105,6 +107,7 @@ void SceneCulling::collectCullingQueries( namespace { const pipeline::PipelineSceneData* pSceneData = nullptr; +const LayoutGraphData* layoutGraph = nullptr; bool isNodeVisible(const Node* node, uint32_t visibility) { return node && ((visibility & node->getLayer()) == node->getLayer()); } @@ -113,10 +116,18 @@ uint32_t isModelVisible(const scene::Model& model, uint32_t visibility) { return visibility & static_cast(model.getVisFlags()); } +bool isReflectProbeMask(const scene::Model& model) { + return ((model.getNode()->getLayer() & REFLECTION_PROBE_DEFAULT_MASK) == model.getNode()->getLayer()) || (REFLECTION_PROBE_DEFAULT_MASK & static_cast(model.getVisFlags())); +} + +bool isIntersectAABB(const geometry::AABB& lAABB, const geometry::AABB& rAABB) { + return !lAABB.aabbAabb(rAABB); +} + bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustum, bool castShadow) { const auto* const modelWorldBounds = model.getWorldBounds(); if (!modelWorldBounds) { - return true; + return false; } geometry::AABB transWorldBounds{}; transWorldBounds.set(modelWorldBounds->getCenter(), modelWorldBounds->getHalfExtents()); @@ -124,35 +135,27 @@ bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustu if (shadows.getType() == scene::ShadowType::PLANAR && castShadow) { modelWorldBounds->transform(shadows.getMatLight(), &transWorldBounds); } - return transWorldBounds.aabbFrustum(frustum); + return !transWorldBounds.aabbFrustum(frustum); } void octreeCulling( const scene::Octree& octree, - const scene::Model* skyboxModelToSkip, + const scene::Model* skyboxModel, const scene::RenderScene& scene, const scene::Camera& camera, const geometry::Frustum& cameraOrLightFrustum, bool bCastShadow, ccstd::vector& models) { const auto visibility = camera.getVisibility(); + const auto camSkyboxFlag = (static_cast(camera.getClearFlag()) & scene::Camera::SKYBOX_FLAG); + if (!bCastShadow && skyboxModel && camSkyboxFlag) { + models.emplace_back(skyboxModel); + } // add instances without world bounds for (const auto& pModel : scene.getModels()) { CC_EXPECTS(pModel); const auto& model = *pModel; - if (!model.isEnabled()) { - continue; - } - // has world bounds, should be in octree - if (model.getWorldBounds()) { - continue; - } - // is skybox, skip - if (&model == skyboxModelToSkip) { - continue; - } - // check cast shadow - if (bCastShadow && !model.isCastShadow()) { + if (!model.isEnabled() || !model.getNode() || model.getWorldBounds() || (bCastShadow && !model.isCastShadow())) { continue; } // filter model by view visibility @@ -173,57 +176,62 @@ void octreeCulling( } void bruteForceCulling( - const scene::Model* skyboxModelToSkip, + const scene::Model* skyboxModel, const scene::RenderScene& scene, const scene::Camera& camera, const geometry::Frustum& cameraOrLightFrustum, bool bCastShadow, + const scene::ReflectionProbe* probe, ccstd::vector& models) { const auto visibility = camera.getVisibility(); + const auto camSkyboxFlag = (static_cast(camera.getClearFlag()) & scene::Camera::SKYBOX_FLAG); + if (!bCastShadow && skyboxModel && camSkyboxFlag) { + models.emplace_back(skyboxModel); + } for (const auto& pModel : scene.getModels()) { CC_EXPECTS(pModel); const auto& model = *pModel; - if (!model.isEnabled()) { + if (!model.isEnabled() || !model.getNode() || !model.getWorldBounds() || (bCastShadow && !model.isCastShadow())) { continue; } - if (bCastShadow && !model.isCastShadow()) { + // lod culling + if (scene.isCulledByLod(&camera, &model)) { continue; } - // filter model by view visibility - if (isNodeVisible(model.getNode(), visibility) || isModelVisible(model, visibility)) { - // frustum culling - if (!isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) { - continue; - } - // is skybox, skip - if (&model == skyboxModelToSkip) { - continue; - } - // lod culling - if (scene.isCulledByLod(&camera, &model)) { - continue; + if (!probe || (probe && probe->getProbeType() == cc::scene::ReflectionProbe::ProbeType::CUBE)) { + // filter model by view visibility + if (isNodeVisible(model.getNode(), visibility) || isModelVisible(model, visibility)) { + // frustum culling + if ((!probe && isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) + || (probe && isIntersectAABB(*model.getWorldBounds(), *probe->getBoundingBox()))) { + continue; + } + + models.emplace_back(&model); } + } else if (isReflectProbeMask(model)) { models.emplace_back(&model); } } } void sceneCulling( - const scene::Model* skyboxModelToSkip, + const scene::Model* skyboxModel, const scene::RenderScene& scene, const scene::Camera& camera, const geometry::Frustum& cameraOrLightFrustum, bool bCastShadow, + const scene::ReflectionProbe* probe, ccstd::vector& models) { const auto* const octree = scene.getOctree(); - if (octree && octree->isEnabled()) { + if (octree && octree->isEnabled() && !probe) { octreeCulling( - *octree, skyboxModelToSkip, + *octree, skyboxModel, scene, camera, cameraOrLightFrustum, bCastShadow, models); } else { bruteForceCulling( - skyboxModelToSkip, - scene, camera, cameraOrLightFrustum, bCastShadow, models); + skyboxModel, + scene, camera, cameraOrLightFrustum, bCastShadow, probe, models); } } @@ -231,29 +239,41 @@ void sceneCulling( void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) { const auto* const skybox = pplSceneData.getSkybox(); - const auto* const skyboxModelToSkip = skybox ? skybox->getModel() : nullptr; + const auto* const skyboxModel = skybox && skybox->isEnabled() ? skybox->getModel() : nullptr; for (const auto& [scene, queries] : sceneQueries) { CC_ENSURES(scene); for (const auto& [key, sourceID] : queries.culledResultIndex) { CC_EXPECTS(key.camera); CC_EXPECTS(key.camera->getScene() == scene); - const auto& camera = *key.camera; const auto* light = key.light; const auto level = key.lightLevel; const auto bCastShadow = key.castShadow; - + const auto* probe = key.probe; + const auto& camera = probe ? *probe->getCamera() : *key.camera; CC_EXPECTS(sourceID < culledResults.size()); auto& models = culledResults[sourceID]; + if (probe) { + sceneCulling( + skyboxModel, + *scene, camera, + camera.getFrustum(), + bCastShadow, + probe, + models); + continue; + } + if (light) { switch (light->getType()) { case scene::LightType::SPOT: sceneCulling( - skyboxModelToSkip, + skyboxModel, *scene, camera, dynamic_cast(light)->getFrustum(), bCastShadow, + nullptr, models); break; case scene::LightType::DIRECTIONAL: { @@ -276,10 +296,11 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) } } sceneCulling( - skyboxModelToSkip, + skyboxModel, *scene, camera, *frustum, bCastShadow, + nullptr, models); } break; default: @@ -288,10 +309,11 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) } } else { sceneCulling( - skyboxModelToSkip, + skyboxModel, *scene, camera, camera.getFrustum(), bCastShadow, + nullptr, models); } } @@ -324,15 +346,23 @@ void addRenderObject( LayoutGraphData::vertex_descriptor phaseLayoutID, const bool bDrawOpaqueOrMask, const bool bDrawBlend, + const bool bDrawProbe, const scene::Camera& camera, const scene::Model& model, NativeRenderQueue& queue) { + if (bDrawProbe) { + queue.probeQueue.applyMacro(*layoutGraph, model, phaseLayoutID); + } const auto& subModels = model.getSubModels(); const auto subModelCount = subModels.size(); for (uint32_t subModelIdx = 0; subModelIdx < subModelCount; ++subModelIdx) { const auto& subModel = subModels[subModelIdx]; const auto& passes = *(subModel->getPasses()); const auto passCount = passes.size(); + auto probeIt = std::find(queue.probeQueue.probeMap.begin(), queue.probeQueue.probeMap.end(), subModel.get()); + if (probeIt != queue.probeQueue.probeMap.end()) { + phaseLayoutID = queue.probeQueue.getDefaultId(*layoutGraph); + } for (uint32_t passIdx = 0; passIdx < passCount; ++passIdx) { auto& pass = *passes[passIdx]; // check phase @@ -388,8 +418,8 @@ void SceneCulling::fillRenderQueues( const bool bDrawBlend = any(sceneData.flags & SceneFlags::TRANSPARENT_OBJECT); const bool bDrawOpaqueOrMask = any(sceneData.flags & (SceneFlags::OPAQUE_OBJECT | SceneFlags::CUTOUT_OBJECT)); const bool bDrawShadowCaster = any(sceneData.flags & SceneFlags::SHADOW_CASTER); - - if (!bDrawShadowCaster && !bDrawBlend && !bDrawOpaqueOrMask) { + const bool bDrawProbe = any(sceneData.flags & SceneFlags::REFLECTION_PROBE); + if (!bDrawShadowCaster && !bDrawBlend && !bDrawOpaqueOrMask && !bDrawProbe) { // nothing to draw continue; } @@ -413,26 +443,12 @@ void SceneCulling::fillRenderQueues( // skybox const auto* camera = sceneData.camera; CC_EXPECTS(camera); - if (!any(sceneData.flags & SceneFlags::SHADOW_CASTER) && - skybox && skybox->isEnabled() && - (static_cast(camera->getClearFlag()) & scene::Camera::SKYBOX_FLAG)) { - CC_EXPECTS(skybox->getModel()); - const auto& model = *skybox->getModel(); - const auto* node = model.getNode(); - float depth = 0; - if (node) { - Vec3 tempVec3{}; - tempVec3 = node->getWorldPosition() - camera->getPosition(); - depth = tempVec3.dot(camera->getForward()); - } - nativeQueue.opaqueQueue.add(model, depth, 0, 0); - } // fill native queue for (const auto* const model : sourceModels) { addRenderObject( phaseLayoutID, bDrawOpaqueOrMask, bDrawBlend, - *sceneData.camera, *model, nativeQueue); + bDrawProbe, *sceneData.camera, *model, nativeQueue); } // post-processing @@ -444,6 +460,7 @@ void SceneCulling::buildRenderQueues( const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData) { pSceneData = &pplSceneData; + layoutGraph = ≶ collectCullingQueries(rg, lg); batchCulling(pplSceneData); fillRenderQueues(rg, pplSceneData); diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp index c7fed6ceedb..45e93a6df84 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp @@ -47,6 +47,9 @@ bool nativevalue_to_se(const cc::render::LightInfo &from, se::Value &to, se::Obj nativevalue_to_se(from.culledByLight, tmp, ctx); obj->setProperty("culledByLight", tmp); + nativevalue_to_se(from.probe, tmp, ctx); + obj->setProperty("light", tmp); + to.setObject(obj); return true; } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index cad5d71c02c..f9a32f4c253 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -36,6 +36,7 @@ #include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/pipeline/custom/RenderCommonFwd.h" #include "cocos/scene/Light.h" +#include "cocos/scene/ReflectionProbe.h" namespace cc { @@ -211,15 +212,18 @@ enum class ClearValueType { struct LightInfo { LightInfo() = default; - LightInfo(IntrusivePtr lightIn, uint32_t levelIn, bool culledByLightIn) noexcept + LightInfo(IntrusivePtr lightIn, uint32_t levelIn, bool culledByLightIn, IntrusivePtr probeIn) noexcept : light(std::move(lightIn)), level(levelIn), - culledByLight(culledByLightIn) {} + culledByLight(culledByLightIn), + probe(std::move(probeIn)) + {} LightInfo(IntrusivePtr lightIn, uint32_t levelIn) noexcept : light(std::move(lightIn)), level(levelIn) {} IntrusivePtr light; + IntrusivePtr probe; uint32_t level{0}; bool culledByLight{false}; }; From 1ce2d37e5c9a02fa3592735dbf61901d923a904c Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 25 Aug 2023 17:35:51 +0800 Subject: [PATCH 34/82] add builtin reflection probe pass builder --- cocos/rendering/custom/pipeline.ts | 5 ++ cocos/rendering/custom/web-pipeline.ts | 5 +- .../pipeline/custom/NativePipeline.cpp | 12 +++ .../pipeline/custom/NativePipelineFwd.h | 1 + .../pipeline/custom/NativePipelineTypes.h | 83 +++++++++++++++++++ .../pipeline/custom/NativeRenderGraph.cpp | 7 ++ .../pipeline/custom/RenderInterfaceFwd.h | 1 + .../pipeline/custom/RenderInterfaceTypes.h | 14 ++++ 8 files changed, 127 insertions(+), 1 deletion(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index d40be0f00fc..474e891b435 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -569,6 +569,10 @@ export interface BasicMultisampleRenderPassBuilder extends BasicRenderPassBuilde stencilMode?: ResolveMode): void; } +export interface BuiltinReflectionProbePassBuilder extends Setter { + addQueue (hint?: QueueHint, phaseName?: string): RenderQueueBuilder; +} + /** * @en BasicPipeline * Basic pipeline provides basic rendering features which are supported on all platforms. @@ -810,6 +814,7 @@ export interface BasicPipeline extends PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ addCopyPass (copyPairs: CopyPair[]): void; + addBuiltinReflectionProbePass (width: number, height: number): BuiltinReflectionProbePassBuilder; /** * @engineInternal */ diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 854a188e6f9..0fa069c40a0 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -29,7 +29,7 @@ import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency } from './types'; import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; -import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder } from './pipeline'; +import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder, BuiltinReflectionProbePassBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; @@ -2011,6 +2011,9 @@ export class WebPipeline implements BasicPipeline { this.execute(); this.endFrame(); } + addBuiltinReflectionProbePass (width: number, height: number): BuiltinReflectionProbePassBuilder { + return {} as BuiltinReflectionProbePassBuilder; + } addRenderPassImpl (width: number, height: number, layoutName: string, count = 1, quality = 0): BasicMultisampleRenderPassBuilder { if (DEBUG) { const stageId = this.layoutGraph.locateChild(this.layoutGraph.nullVertex(), layoutName); diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index 7896ae83828..e4cd4b16429 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -677,6 +677,18 @@ void NativePipeline::endFrame() { // noop } +BuiltinReflectionProbePassBuilder *NativePipeline::addBuiltinReflectionProbePass( + uint32_t width, uint32_t height) { + std::ignore = width; + std::ignore = height; + const auto &layoutGraph = programLibrary->layoutGraph; + + auto *builder = ccnew NativeBuiltinReflectionProbePassBuilder( + this, &renderGraph, RenderGraph::null_vertex(), &layoutGraph, LayoutGraph::null_vertex()); + + return builder; +} + RenderPassBuilder *NativePipeline::addRenderPass( uint32_t width, uint32_t height, const ccstd::string &passName) { diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 846d97ac32d..c87a72c82d6 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -49,6 +49,7 @@ class NativeRenderPassBuilder; class NativeMultisampleRenderPassBuilder; class NativeComputeQueueBuilder; class NativeComputePassBuilder; +class NativeBuiltinReflectionProbePassBuilder; struct RenderInstancingQueue; struct DrawInstance; struct RenderDrawQueue; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 8d24abdb9cc..43447a1ce2e 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -891,6 +891,88 @@ class NativeComputePassBuilder final : public ComputePassBuilder, public NativeS void setCustomShaderStages(const ccstd::string &name, gfx::ShaderStageFlagBit stageFlags) override; }; +class NativeBuiltinReflectionProbePassBuilder final : public BuiltinReflectionProbePassBuilder, public NativeSetter { +public: + NativeBuiltinReflectionProbePassBuilder(const PipelineRuntime* pipelineRuntimeIn, RenderGraph* renderGraphIn, uint32_t nodeIDIn, const LayoutGraphData* layoutGraphIn, uint32_t layoutIDIn) noexcept + : NativeSetter(pipelineRuntimeIn, renderGraphIn, nodeIDIn, layoutGraphIn, layoutIDIn) {} + + ccstd::string getName() const override { + return NativeRenderNode::getName(); + } + void setName(const ccstd::string &name) override { + NativeRenderNode::setName(name); + } + void setCustomBehavior(const ccstd::string &name) override { + NativeRenderNode::setCustomBehavior(name); + } + + void setMat4(const ccstd::string &name, const Mat4 &mat) override { + NativeSetter::setMat4(name, mat); + } + void setQuaternion(const ccstd::string &name, const Quaternion &quat) override { + NativeSetter::setQuaternion(name, quat); + } + void setColor(const ccstd::string &name, const gfx::Color &color) override { + NativeSetter::setColor(name, color); + } + void setVec4(const ccstd::string &name, const Vec4 &vec) override { + NativeSetter::setVec4(name, vec); + } + void setVec2(const ccstd::string &name, const Vec2 &vec) override { + NativeSetter::setVec2(name, vec); + } + void setFloat(const ccstd::string &name, float v) override { + NativeSetter::setFloat(name, v); + } + void setArrayBuffer(const ccstd::string &name, const ArrayBuffer *arrayBuffer) override { + NativeSetter::setArrayBuffer(name, arrayBuffer); + } + void setBuffer(const ccstd::string &name, gfx::Buffer *buffer) override { + NativeSetter::setBuffer(name, buffer); + } + void setTexture(const ccstd::string &name, gfx::Texture *texture) override { + NativeSetter::setTexture(name, texture); + } + void setReadWriteBuffer(const ccstd::string &name, gfx::Buffer *buffer) override { + NativeSetter::setReadWriteBuffer(name, buffer); + } + void setReadWriteTexture(const ccstd::string &name, gfx::Texture *texture) override { + NativeSetter::setReadWriteTexture(name, texture); + } + void setSampler(const ccstd::string &name, gfx::Sampler *sampler) override { + NativeSetter::setSampler(name, sampler); + } + void setBuiltinCameraConstants(const scene::Camera *camera) override { + NativeSetter::setBuiltinCameraConstants(camera); + } + void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { + NativeSetter::setBuiltinShadowMapConstants(light); + } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } + void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + } + void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightViewConstants(light); + } + + RenderQueueBuilder *addQueue(QueueHint hint, const ccstd::string &phaseName) override; +}; + struct RenderInstancingQueue { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT @@ -1376,6 +1458,7 @@ class NativePipeline final : public Pipeline { void endFrame() override; void addResolvePass(const ccstd::vector &resolvePairs) override; void addCopyPass(const ccstd::vector ©Pairs) override; + BuiltinReflectionProbePassBuilder *addBuiltinReflectionProbePass(uint32_t width, uint32_t height) override; gfx::DescriptorSetLayout *getDescriptorSetLayout(const ccstd::string &shaderName, UpdateFrequency freq) override; uint32_t addStorageBuffer(const ccstd::string &name, gfx::Format format, uint32_t size, ResourceResidency residency) override; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 960cb08d0d4..1b492fe7b27 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -1312,6 +1312,13 @@ ComputeQueueBuilder *NativeComputePassBuilder::addQueue(const ccstd::string &pha return new NativeComputeQueueBuilder(pipelineRuntime, renderGraph, queueID, layoutGraph, phaseLayoutID); } +RenderQueueBuilder* NativeBuiltinReflectionProbePassBuilder::addQueue( + QueueHint hint, const ccstd::string &phaseName) { + std::ignore = hint; + std::ignore = phaseName; + return nullptr; +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h index 7a72a5f60e8..26fc91e6f73 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h @@ -50,6 +50,7 @@ class Setter; class RenderQueueBuilder; class BasicRenderPassBuilder; class BasicMultisampleRenderPassBuilder; +class BuiltinReflectionProbePassBuilder; class BasicPipeline; class RenderSubpassBuilder; class MultisampleRenderSubpassBuilder; diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 29e13290601..b83a01f265c 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -676,6 +676,19 @@ class BasicMultisampleRenderPassBuilder : public BasicRenderPassBuilder { } }; +class BuiltinReflectionProbePassBuilder : public Setter { +public: + BuiltinReflectionProbePassBuilder() noexcept = default; + + virtual RenderQueueBuilder *addQueue(QueueHint hint, const ccstd::string &phaseName) = 0; + RenderQueueBuilder *addQueue() { + return addQueue(QueueHint::NONE, "default"); + } + RenderQueueBuilder *addQueue(QueueHint hint) { + return addQueue(hint, "default"); + } +}; + /** * @en BasicPipeline * Basic pipeline provides basic rendering features which are supported on all platforms. @@ -844,6 +857,7 @@ class BasicPipeline : public PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ virtual void addCopyPass(const ccstd::vector ©Pairs) = 0; + virtual BuiltinReflectionProbePassBuilder *addBuiltinReflectionProbePass(uint32_t width, uint32_t height) = 0; /** * @engineInternal */ From 9c7a443a3c237a7e29a72a4700da978918d6b9e1 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 25 Aug 2023 17:40:42 +0800 Subject: [PATCH 35/82] Update --- cocos/rendering/custom/executor.ts | 1 + .../renderer/pipeline/custom/NativeExecutor.cpp | 3 +++ .../renderer/pipeline/custom/NativePipelineTypes.cpp | 8 ++++---- .../renderer/pipeline/custom/NativePipelineTypes.h | 12 ++++++++---- .../renderer/pipeline/custom/NativeSceneCulling.cpp | 1 + .../renderer/pipeline/custom/RenderCommonTypes.h | 3 +-- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 9a90bda44a1..5475671c346 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -133,6 +133,7 @@ import { getRenderArea, mergeSrcToTargetDesc, updateGlobalDescBinding, + validPunctualLightsCulling, } from './define'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; import { SceneCulling } from './scene-culling'; diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index bacbc8a90a6..da02b3a9200 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -1392,6 +1392,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); queue.transparentInstancingQueue.recordCommandBuffer( ctx.currentPass, ctx.cmdBuff); + if(any(sceneData.flags & SceneFlags::REFLECTION_PROBE)) { + queue.probeQueue.removeMacro(); + } if (any(sceneData.flags & SceneFlags::UI)) { submitUICommands(ctx.currentPass, ctx.currentPassLayoutID, camera, ctx.cmdBuff); diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 13402865da4..55ae3721287 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -224,7 +224,7 @@ PipelineCustomization::PipelineCustomization(PipelineCustomization const& rhs, c renderQueues(rhs.renderQueues, alloc), renderCommands(rhs.renderCommands, alloc) {} -void ProbeHelperQueue::removeMacro() +void ProbeHelperQueue::removeMacro() const { for (auto subModel : probeMap) { std::vector patches; @@ -242,7 +242,7 @@ void ProbeHelperQueue::removeMacro() } } -int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) +int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) const { const auto& passes = subModel->getPasses(); for (size_t k = 0; k < passes->size(); ++k) { @@ -278,9 +278,9 @@ void ProbeHelperQueue::applyMacro(const LayoutGraphData & lg, const cc::scene::M std::vector patches; patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); const cc::scene::IMacroPatch useRGBEPatch = {"CC_USE_RGBE_OUTPUT", true}; - patches.push_back(useRGBEPatch); + patches.emplace_back(useRGBEPatch); subModel->onMacroPatchesStateChanged(patches); - probeMap.push_back(subModel); + probeMap.emplace_back(subModel); } } } diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 9780cc9615f..5c5e075712f 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -932,15 +932,19 @@ struct DrawInstance { }; struct ProbeHelperQueue { - std::vector probeMap; + ccstd::pmr::vector probeMap; - int getDefaultId(const LayoutGraphData &lg) { + inline int getDefaultId(const LayoutGraphData &lg) const { return locate(locate(LayoutGraphData::null_vertex(), "default", lg), "default", lg); } - void removeMacro(); + inline void clear() { + probeMap.clear(); + } + + void removeMacro() const; - int getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId); + int getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) const; void applyMacro(const LayoutGraphData &lg, const cc::scene::Model& model, int probeLayoutId); }; diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index aaf808a6329..a9f76757b7c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -13,6 +13,7 @@ namespace cc { namespace render { const static uint32_t REFLECTION_PROBE_DEFAULT_MASK = ~static_cast(pipeline::LayerList::UI_2D) & ~static_cast(pipeline::LayerList::PROFILER) & ~static_cast(pipeline::LayerList::UI_3D) & ~static_cast(pipeline::LayerList::GIZMOS) & ~static_cast(pipeline::LayerList::SCENE_GIZMO) & ~static_cast(pipeline::LayerList::EDITOR); void NativeRenderQueue::clear() noexcept { + probeQueue.clear(); opaqueQueue.instances.clear(); transparentQueue.instances.clear(); opaqueInstancingQueue.clear(); diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index ea63634c0a4..91f8c5c6917 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -226,8 +226,7 @@ struct LightInfo { : light(std::move(lightIn)), probe(probeIn), level(levelIn), - culledByLight(culledByLightIn), - probe(std::move(probeIn)) + culledByLight(culledByLightIn) {} LightInfo(IntrusivePtr lightIn, uint32_t levelIn) noexcept : light(std::move(lightIn)), From cee296c0d2ca971e3cadc799a384fad7c0f026cd Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 25 Aug 2023 17:56:52 +0800 Subject: [PATCH 36/82] remove render queue --- cocos/rendering/custom/pipeline.ts | 6 +- cocos/rendering/custom/web-pipeline.ts | 6 +- .../pipeline/custom/NativePipeline.cpp | 8 +- .../pipeline/custom/NativePipelineFwd.h | 1 - .../pipeline/custom/NativePipelineTypes.h | 84 +------------------ .../pipeline/custom/NativeRenderGraph.cpp | 7 -- .../pipeline/custom/RenderInterfaceFwd.h | 1 - .../pipeline/custom/RenderInterfaceTypes.h | 15 +--- 8 files changed, 7 insertions(+), 121 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 474e891b435..f66c31e8cfd 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -569,10 +569,6 @@ export interface BasicMultisampleRenderPassBuilder extends BasicRenderPassBuilde stencilMode?: ResolveMode): void; } -export interface BuiltinReflectionProbePassBuilder extends Setter { - addQueue (hint?: QueueHint, phaseName?: string): RenderQueueBuilder; -} - /** * @en BasicPipeline * Basic pipeline provides basic rendering features which are supported on all platforms. @@ -814,7 +810,7 @@ export interface BasicPipeline extends PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ addCopyPass (copyPairs: CopyPair[]): void; - addBuiltinReflectionProbePass (width: number, height: number): BuiltinReflectionProbePassBuilder; + addBuiltinReflectionProbePass (width: number, height: number): void; /** * @engineInternal */ diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 0fa069c40a0..fff274324a1 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -29,7 +29,7 @@ import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency } from './types'; import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; -import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder, BuiltinReflectionProbePassBuilder } from './pipeline'; +import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; @@ -2011,8 +2011,8 @@ export class WebPipeline implements BasicPipeline { this.execute(); this.endFrame(); } - addBuiltinReflectionProbePass (width: number, height: number): BuiltinReflectionProbePassBuilder { - return {} as BuiltinReflectionProbePassBuilder; + addBuiltinReflectionProbePass (width: number, height: number): void { + // TODO } addRenderPassImpl (width: number, height: number, layoutName: string, count = 1, quality = 0): BasicMultisampleRenderPassBuilder { if (DEBUG) { diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index e4cd4b16429..40fd4392591 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -677,16 +677,10 @@ void NativePipeline::endFrame() { // noop } -BuiltinReflectionProbePassBuilder *NativePipeline::addBuiltinReflectionProbePass( +void NativePipeline::addBuiltinReflectionProbePass( uint32_t width, uint32_t height) { std::ignore = width; std::ignore = height; - const auto &layoutGraph = programLibrary->layoutGraph; - - auto *builder = ccnew NativeBuiltinReflectionProbePassBuilder( - this, &renderGraph, RenderGraph::null_vertex(), &layoutGraph, LayoutGraph::null_vertex()); - - return builder; } RenderPassBuilder *NativePipeline::addRenderPass( diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index c87a72c82d6..846d97ac32d 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -49,7 +49,6 @@ class NativeRenderPassBuilder; class NativeMultisampleRenderPassBuilder; class NativeComputeQueueBuilder; class NativeComputePassBuilder; -class NativeBuiltinReflectionProbePassBuilder; struct RenderInstancingQueue; struct DrawInstance; struct RenderDrawQueue; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 43447a1ce2e..e2d42b80293 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -891,88 +891,6 @@ class NativeComputePassBuilder final : public ComputePassBuilder, public NativeS void setCustomShaderStages(const ccstd::string &name, gfx::ShaderStageFlagBit stageFlags) override; }; -class NativeBuiltinReflectionProbePassBuilder final : public BuiltinReflectionProbePassBuilder, public NativeSetter { -public: - NativeBuiltinReflectionProbePassBuilder(const PipelineRuntime* pipelineRuntimeIn, RenderGraph* renderGraphIn, uint32_t nodeIDIn, const LayoutGraphData* layoutGraphIn, uint32_t layoutIDIn) noexcept - : NativeSetter(pipelineRuntimeIn, renderGraphIn, nodeIDIn, layoutGraphIn, layoutIDIn) {} - - ccstd::string getName() const override { - return NativeRenderNode::getName(); - } - void setName(const ccstd::string &name) override { - NativeRenderNode::setName(name); - } - void setCustomBehavior(const ccstd::string &name) override { - NativeRenderNode::setCustomBehavior(name); - } - - void setMat4(const ccstd::string &name, const Mat4 &mat) override { - NativeSetter::setMat4(name, mat); - } - void setQuaternion(const ccstd::string &name, const Quaternion &quat) override { - NativeSetter::setQuaternion(name, quat); - } - void setColor(const ccstd::string &name, const gfx::Color &color) override { - NativeSetter::setColor(name, color); - } - void setVec4(const ccstd::string &name, const Vec4 &vec) override { - NativeSetter::setVec4(name, vec); - } - void setVec2(const ccstd::string &name, const Vec2 &vec) override { - NativeSetter::setVec2(name, vec); - } - void setFloat(const ccstd::string &name, float v) override { - NativeSetter::setFloat(name, v); - } - void setArrayBuffer(const ccstd::string &name, const ArrayBuffer *arrayBuffer) override { - NativeSetter::setArrayBuffer(name, arrayBuffer); - } - void setBuffer(const ccstd::string &name, gfx::Buffer *buffer) override { - NativeSetter::setBuffer(name, buffer); - } - void setTexture(const ccstd::string &name, gfx::Texture *texture) override { - NativeSetter::setTexture(name, texture); - } - void setReadWriteBuffer(const ccstd::string &name, gfx::Buffer *buffer) override { - NativeSetter::setReadWriteBuffer(name, buffer); - } - void setReadWriteTexture(const ccstd::string &name, gfx::Texture *texture) override { - NativeSetter::setReadWriteTexture(name, texture); - } - void setSampler(const ccstd::string &name, gfx::Sampler *sampler) override { - NativeSetter::setSampler(name, sampler); - } - void setBuiltinCameraConstants(const scene::Camera *camera) override { - NativeSetter::setBuiltinCameraConstants(camera); - } - void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { - NativeSetter::setBuiltinShadowMapConstants(light); - } - void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { - NativeSetter::setBuiltinDirectionalLightConstants(light, camera); - } - void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { - NativeSetter::setBuiltinSphereLightConstants(light, camera); - } - void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { - NativeSetter::setBuiltinSpotLightConstants(light, camera); - } - void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { - NativeSetter::setBuiltinPointLightConstants(light, camera); - } - void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { - NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); - } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); - } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); - } - - RenderQueueBuilder *addQueue(QueueHint hint, const ccstd::string &phaseName) override; -}; - struct RenderInstancingQueue { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT @@ -1458,7 +1376,7 @@ class NativePipeline final : public Pipeline { void endFrame() override; void addResolvePass(const ccstd::vector &resolvePairs) override; void addCopyPass(const ccstd::vector ©Pairs) override; - BuiltinReflectionProbePassBuilder *addBuiltinReflectionProbePass(uint32_t width, uint32_t height) override; + void addBuiltinReflectionProbePass(uint32_t width, uint32_t height) override; gfx::DescriptorSetLayout *getDescriptorSetLayout(const ccstd::string &shaderName, UpdateFrequency freq) override; uint32_t addStorageBuffer(const ccstd::string &name, gfx::Format format, uint32_t size, ResourceResidency residency) override; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 1b492fe7b27..960cb08d0d4 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -1312,13 +1312,6 @@ ComputeQueueBuilder *NativeComputePassBuilder::addQueue(const ccstd::string &pha return new NativeComputeQueueBuilder(pipelineRuntime, renderGraph, queueID, layoutGraph, phaseLayoutID); } -RenderQueueBuilder* NativeBuiltinReflectionProbePassBuilder::addQueue( - QueueHint hint, const ccstd::string &phaseName) { - std::ignore = hint; - std::ignore = phaseName; - return nullptr; -} - } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h index 26fc91e6f73..7a72a5f60e8 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h @@ -50,7 +50,6 @@ class Setter; class RenderQueueBuilder; class BasicRenderPassBuilder; class BasicMultisampleRenderPassBuilder; -class BuiltinReflectionProbePassBuilder; class BasicPipeline; class RenderSubpassBuilder; class MultisampleRenderSubpassBuilder; diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index b83a01f265c..36519a36c76 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -676,19 +676,6 @@ class BasicMultisampleRenderPassBuilder : public BasicRenderPassBuilder { } }; -class BuiltinReflectionProbePassBuilder : public Setter { -public: - BuiltinReflectionProbePassBuilder() noexcept = default; - - virtual RenderQueueBuilder *addQueue(QueueHint hint, const ccstd::string &phaseName) = 0; - RenderQueueBuilder *addQueue() { - return addQueue(QueueHint::NONE, "default"); - } - RenderQueueBuilder *addQueue(QueueHint hint) { - return addQueue(hint, "default"); - } -}; - /** * @en BasicPipeline * Basic pipeline provides basic rendering features which are supported on all platforms. @@ -857,7 +844,7 @@ class BasicPipeline : public PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ virtual void addCopyPass(const ccstd::vector ©Pairs) = 0; - virtual BuiltinReflectionProbePassBuilder *addBuiltinReflectionProbePass(uint32_t width, uint32_t height) = 0; + virtual void addBuiltinReflectionProbePass(uint32_t width, uint32_t height) = 0; /** * @engineInternal */ From 72522b09049e277dfe3f48f792412033bbc96dc2 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Tue, 29 Aug 2023 09:56:53 +0800 Subject: [PATCH 37/82] Complete reflection probes for the native new pipeline --- cocos/rendering/custom/custom-pipeline.ts | 58 ++++++++---- cocos/rendering/custom/pipeline.ts | 2 +- cocos/rendering/custom/web-pipeline.ts | 29 ++++-- .../post-process/post-process-builder.ts | 2 +- .../pipeline/custom/NativePipeline.cpp | 88 ++++++++++++++++++- .../pipeline/custom/NativePipelineTypes.h | 2 +- .../pipeline/custom/RenderInterfaceTypes.h | 2 +- 7 files changed, 156 insertions(+), 27 deletions(-) diff --git a/cocos/rendering/custom/custom-pipeline.ts b/cocos/rendering/custom/custom-pipeline.ts index 993f71c6b50..3f93ca50e0b 100644 --- a/cocos/rendering/custom/custom-pipeline.ts +++ b/cocos/rendering/custom/custom-pipeline.ts @@ -141,14 +141,21 @@ export class TestPipelineBuilder implements PipelineBuilder { ppl.update(camera); const info = this.prepareGameCamera(ppl, camera); this.prepareSceneInfo(camera.scene, camera.frustum, this._sceneInfo); - this.buildForward(ppl, camera, - info.id, info.width, info.height); + this.buildForward( + ppl, + camera, + info.id, + info.width, + info.height, + ); } } // implementation - private prepareSceneInfo (scene: Readonly, + private prepareSceneInfo ( + scene: Readonly, frustum: geometry.Frustum, - sceneInfo: SceneInfo): void { + sceneInfo: SceneInfo, + ): void { // clear scene info sceneInfo.reset(); // spot lights @@ -259,9 +266,14 @@ export class TestPipelineBuilder implements PipelineBuilder { ppl.updateDepthStencil(`SpotLightShadowDepth${id}2`, shadowSize.x, shadowSize.y); ppl.updateDepthStencil(`SpotLightShadowDepth${id}3`, shadowSize.x, shadowSize.y); } - private buildForwardTiled (ppl: BasicPipeline, - camera: Camera, id: number, width: number, height: number, - sceneInfo: SceneInfo): void { + private buildForwardTiled ( + ppl: BasicPipeline, + camera: Camera, + id: number, + width: number, + height: number, + sceneInfo: SceneInfo, + ): void { assert(this._tiled); assert(camera.scene !== null); // init @@ -288,8 +300,13 @@ export class TestPipelineBuilder implements PipelineBuilder { .addSceneOfCamera(camera, new LightInfo(), SceneFlags.BLEND); } } - private buildForward (ppl: BasicPipeline, - camera: Camera, id: number, width: number, height: number): void { + private buildForward ( + ppl: BasicPipeline, + camera: Camera, + id: number, + width: number, + height: number, + ): void { assert(camera.scene !== null); if (camera.scene === null) { return; @@ -325,8 +342,11 @@ export class TestPipelineBuilder implements PipelineBuilder { // queue.addSceneCulledByDirectionalLight(camera, // SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, // light, 0); - queue.addSceneOfCamera(camera, new LightInfo(light, 0), - SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER); + queue.addSceneOfCamera( + camera, + new LightInfo(light, 0), + SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, + ); } else { const csmLevel = ppl.pipelineSceneData.csmSupported ? light.csmLevel : 1; @@ -337,8 +357,11 @@ export class TestPipelineBuilder implements PipelineBuilder { // queue.addSceneCulledByDirectionalLight(camera, // SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, // light, level); - queue.addSceneOfCamera(camera, new LightInfo(light, level), - SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER); + queue.addSceneOfCamera( + camera, + new LightInfo(light, level), + SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, + ); } } } @@ -352,8 +375,13 @@ export class TestPipelineBuilder implements PipelineBuilder { vp.width = Math.max(1, vp.width); vp.height = Math.max(1, vp.height); } - private getMainLightViewport (light: DirectionalLight, w: number, h: number, level: number, - vp: Viewport): void { + private getMainLightViewport ( + light: DirectionalLight, + w: number, + h: number, + level: number, + vp: Viewport, + ): void { if (light.shadowFixedArea || light.csmLevel === CSMLevel.LEVEL_1) { vp.left = 0; vp.top = 0; diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index f66c31e8cfd..6eb4e93c9cb 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -810,7 +810,7 @@ export interface BasicPipeline extends PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ addCopyPass (copyPairs: CopyPair[]): void; - addBuiltinReflectionProbePass (width: number, height: number): void; + addBuiltinReflectionProbePass (width: number, height: number, camera: Camera): void; /** * @engineInternal */ diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index fff274324a1..8f3c3f8a47e 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -24,14 +24,14 @@ /* eslint-disable max-len */ import { systemInfo } from 'pal/system-info'; -import { DEBUG } from 'internal:constants'; +import { DEBUG, EDITOR } from 'internal:constants'; import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, Sampler, Swapchain, Texture, ClearFlagBit, DescriptorSet, deviceManager, Viewport, API, CommandBuffer, Type, SamplerInfo, Filter, Address, DescriptorSetInfo, LoadOp, StoreOp, ShaderStageFlagBit, BufferInfo, TextureInfo, TextureType, UniformBlock, ResolveMode, SampleCount, Color } from '../../gfx'; import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency } from './types'; import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; -import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight } from '../../render-scene/scene'; +import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight, ProbeType } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; import { DescriptorSetData, DescriptorSetLayoutData, LayoutGraphData } from './layout-graph'; import { Executor } from './executor'; @@ -51,12 +51,13 @@ import { CustomPipelineBuilder } from './custom-pipeline'; import { decideProfilerCamera } from '../pipeline-funcs'; import { DebugViewCompositeType } from '../debug-view'; import { getUBOTypeCount } from './utils'; -import { initGlobalDescBinding } from './define'; +import { buildReflectionProbePass, initGlobalDescBinding } from './define'; import { createGfxDescriptorSetsAndPipelines } from './layout-graph-utils'; import { Root } from '../../root'; import { CSMLayers, CSMShadowLayer } from '../shadow/csm-layers'; import { Scene } from '../../scene-graph'; import { Director } from '../../game'; +import { ReflectionProbeManager } from '../../3d'; const _uboVec = new Vec4(); const _uboVec3 = new Vec3(); @@ -2011,8 +2012,26 @@ export class WebPipeline implements BasicPipeline { this.execute(); this.endFrame(); } - addBuiltinReflectionProbePass (width: number, height: number): void { - // TODO + addBuiltinReflectionProbePass (width: number, height: number, camera: Camera): void { + const reflectionProbeManager = cclegacy.internal.reflectionProbeManager as ReflectionProbeManager; + if (!reflectionProbeManager) return; + const probes = reflectionProbeManager.getProbes(); + if (probes.length === 0) return; + for (let i = 0; i < probes.length; i++) { + const probe = probes[i]; + if (probe.needRender) { + if (probes[i].probeType === ProbeType.PLANAR) { + buildReflectionProbePass(camera, this, probe, probe.realtimePlanarTexture!.window!, 0); + } else if (EDITOR) { + for (let faceIdx = 0; faceIdx < probe.bakedCubeTextures.length; faceIdx++) { + probe.updateCameraDir(faceIdx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + buildReflectionProbePass(camera, this, probe, probe.bakedCubeTextures[faceIdx].window!, faceIdx); + } + probe.needRender = false; + } + } + } } addRenderPassImpl (width: number, height: number, layoutName: string, count = 1, quality = 0): BasicMultisampleRenderPassBuilder { if (DEBUG) { diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index 5dd938caef3..ecd1ac9338e 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -173,7 +173,7 @@ export class PostProcessBuilder implements PipelineBuilder { this.applyPreviewCamera(camera); } - buildReflectionProbePasss(camera, ppl); + ppl.addBuiltinReflectionProbePass(0, 0, camera); passContext.postProcess = camera.postProcess || globalPP; diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index 40fd4392591..98b86653ca6 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -34,6 +34,7 @@ #include "cocos/renderer/pipeline/custom/details/GslUtils.h" #include "cocos/scene/RenderScene.h" #include "cocos/scene/RenderWindow.h" +#include "cocos/scene/ReflectionProbeManager.h" #if CC_USE_DEBUG_RENDERER #include "profiler/DebugRenderer.h" #endif @@ -676,11 +677,92 @@ void NativePipeline::update(const scene::Camera *camera) { void NativePipeline::endFrame() { // noop } +namespace { + gfx::LoadOp getLoadOpOfClearFlag(gfx::ClearFlagBit clearFlag, AttachmentType attachment) { + gfx::LoadOp loadOp = gfx::LoadOp::CLEAR; + if (!(clearFlag & gfx::ClearFlagBit::COLOR) && attachment == AttachmentType::RENDER_TARGET) { + if (static_cast(clearFlag) & cc::scene::Camera::SKYBOX_FLAG) { + loadOp = gfx::LoadOp::CLEAR; + } else { + loadOp = gfx::LoadOp::LOAD; + } + } + if ((clearFlag & gfx::ClearFlagBit::DEPTH_STENCIL) != gfx::ClearFlagBit::DEPTH_STENCIL && attachment == AttachmentType::DEPTH_STENCIL) { + if (!(clearFlag & gfx::ClearFlagBit::DEPTH)) { + loadOp = gfx::LoadOp::LOAD; + } + if (!(clearFlag & gfx::ClearFlagBit::STENCIL)) { + loadOp = gfx::LoadOp::LOAD; + } + } + return loadOp; + } + void updateCameraUBO(Setter &setter, const scene::Camera *camera, NativePipeline &ppl) { + auto sceneData = ppl.pipelineSceneData; + auto skybox = sceneData->getSkybox(); + setter.setBuiltinCameraConstants(camera); + + } + void buildReflectionProbePass(const scene::Camera *camera, + render::NativePipeline *pipeline, + const scene::ReflectionProbe *probe, + scene::RenderWindow *renderWindow, + int faceIdx) { + const std::string cameraName = "Camera" + std::to_string(faceIdx); + auto &area = probe->renderArea(); + int width = area.x; + int height = area.y; + const auto *probeCamera = probe->getCamera(); + const std::string probePassRTName = "reflectionProbePassColor" + cameraName; + const std::string probePassDSName = "reflectionProbePassDS" + cameraName; + if (!pipeline->containsResource(probePassRTName)) { + pipeline->addRenderWindow(probePassRTName, gfx::Format::RGBA8, width, height, renderWindow); + pipeline->addDepthStencil(probePassDSName, gfx::Format::DEPTH_STENCIL, width, height, ResourceResidency::EXTERNAL); + } + pipeline->updateRenderWindow(probePassRTName, renderWindow); + pipeline->updateDepthStencil(probePassDSName, width, height, gfx::Format::DEPTH_STENCIL); + auto *passBuilder = pipeline->addRenderPass(width, height, "default"); + passBuilder->setName("ReflectionProbePass"+faceIdx); + gfx::Viewport currViewport{}; + currViewport.width = width; + currViewport.height = height; + passBuilder->setViewport(currViewport); + gfx::Color clearColor{}; + clearColor.x = probeCamera->getClearColor().x; + clearColor.y = probeCamera->getClearColor().y; + clearColor.z = probeCamera->getClearColor().z; + clearColor.w = probeCamera->getClearColor().w; + passBuilder->addRenderTarget(probePassRTName, + getLoadOpOfClearFlag(probeCamera->getClearFlag(), AttachmentType::RENDER_TARGET), + gfx::StoreOp::STORE, + clearColor); + passBuilder->addDepthStencil(probePassDSName, + getLoadOpOfClearFlag(probeCamera->getClearFlag(), AttachmentType::DEPTH_STENCIL), + gfx::StoreOp::STORE, + probeCamera->getClearDepth(), + probeCamera->getClearStencil(), + probeCamera->getClearFlag()); + auto* queueBuilder = passBuilder->addQueue(QueueHint::RENDER_OPAQUE, "reflect-map"); + LightInfo lightInfo{}; + lightInfo.probe = const_cast(probe); + queueBuilder->addSceneOfCamera(const_cast(probeCamera), lightInfo, SceneFlags::REFLECTION_PROBE | SceneFlags::OPAQUE_OBJECT); + updateCameraUBO(*queueBuilder, probeCamera, *pipeline); + } +} void NativePipeline::addBuiltinReflectionProbePass( - uint32_t width, uint32_t height) { - std::ignore = width; - std::ignore = height; + uint32_t width, uint32_t height, const scene::Camera *camera) { + const auto* reflectProbeManager = scene::ReflectionProbeManager::getInstance(); + if (!reflectProbeManager) return; + const auto &probes = reflectProbeManager->getAllProbes(); + for (int i = 0; i < probes.size(); i++) { + auto* probe = probes[i]; + if (probe->needRender()) { + if (probe->getProbeType() == scene::ReflectionProbe::ProbeType::PLANAR) { + buildReflectionProbePass(camera, this, probe, probe->getRealtimePlanarTexture()->getWindow(), 0); + } + } + } } RenderPassBuilder *NativePipeline::addRenderPass( diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index eb7bd6a7b92..86e70d8a5a4 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1397,7 +1397,7 @@ class NativePipeline final : public Pipeline { void endFrame() override; void addResolvePass(const ccstd::vector &resolvePairs) override; void addCopyPass(const ccstd::vector ©Pairs) override; - void addBuiltinReflectionProbePass(uint32_t width, uint32_t height) override; + void addBuiltinReflectionProbePass(uint32_t width, uint32_t height, const scene::Camera *camera) override; gfx::DescriptorSetLayout *getDescriptorSetLayout(const ccstd::string &shaderName, UpdateFrequency freq) override; uint32_t addStorageBuffer(const ccstd::string &name, gfx::Format format, uint32_t size, ResourceResidency residency) override; diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 36519a36c76..9dce67da144 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -844,7 +844,7 @@ class BasicPipeline : public PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ virtual void addCopyPass(const ccstd::vector ©Pairs) = 0; - virtual void addBuiltinReflectionProbePass(uint32_t width, uint32_t height) = 0; + virtual void addBuiltinReflectionProbePass(uint32_t width, uint32_t height, const scene::Camera *camera) = 0; /** * @engineInternal */ From f444e0b81a73186a5f1f64691a88614c618b1fe8 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Tue, 29 Aug 2023 10:26:19 +0800 Subject: [PATCH 38/82] Fixed lint --- .../renderer/pipeline/custom/NativePipeline.cpp | 12 +++++++----- .../renderer/pipeline/custom/NativePipelineTypes.cpp | 8 +++----- .../renderer/pipeline/custom/NativePipelineTypes.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index 98b86653ca6..737f2a05fae 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -677,7 +677,9 @@ void NativePipeline::update(const scene::Camera *camera) { void NativePipeline::endFrame() { // noop } + namespace { + gfx::LoadOp getLoadOpOfClearFlag(gfx::ClearFlagBit clearFlag, AttachmentType attachment) { gfx::LoadOp loadOp = gfx::LoadOp::CLEAR; if (!(clearFlag & gfx::ClearFlagBit::COLOR) && attachment == AttachmentType::RENDER_TARGET) { @@ -699,7 +701,7 @@ namespace { } void updateCameraUBO(Setter &setter, const scene::Camera *camera, NativePipeline &ppl) { auto sceneData = ppl.pipelineSceneData; - auto skybox = sceneData->getSkybox(); + auto* skybox = sceneData->getSkybox(); setter.setBuiltinCameraConstants(camera); } @@ -709,7 +711,7 @@ namespace { scene::RenderWindow *renderWindow, int faceIdx) { const std::string cameraName = "Camera" + std::to_string(faceIdx); - auto &area = probe->renderArea(); + const auto &area = probe->renderArea(); int width = area.x; int height = area.y; const auto *probeCamera = probe->getCamera(); @@ -748,15 +750,15 @@ namespace { queueBuilder->addSceneOfCamera(const_cast(probeCamera), lightInfo, SceneFlags::REFLECTION_PROBE | SceneFlags::OPAQUE_OBJECT); updateCameraUBO(*queueBuilder, probeCamera, *pipeline); } -} + +} // namespace void NativePipeline::addBuiltinReflectionProbePass( uint32_t width, uint32_t height, const scene::Camera *camera) { const auto* reflectProbeManager = scene::ReflectionProbeManager::getInstance(); if (!reflectProbeManager) return; const auto &probes = reflectProbeManager->getAllProbes(); - for (int i = 0; i < probes.size(); i++) { - auto* probe = probes[i]; + for (auto* probe : probes) { if (probe->needRender()) { if (probe->getProbeType() == scene::ReflectionProbe::ProbeType::PLANAR) { buildReflectionProbePass(camera, this, probe, probe->getRealtimePlanarTexture()->getWindow(), 0); diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 55ae3721287..336596af830 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -226,7 +226,7 @@ PipelineCustomization::PipelineCustomization(PipelineCustomization const& rhs, c void ProbeHelperQueue::removeMacro() const { - for (auto subModel : probeMap) { + for (auto* subModel : probeMap) { std::vector patches; patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); @@ -242,7 +242,7 @@ void ProbeHelperQueue::removeMacro() const } } -int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) const +int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) { const auto& passes = subModel->getPasses(); for (size_t k = 0; k < passes->size(); ++k) { @@ -256,9 +256,7 @@ int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr>& subModels = model.getSubModels(); - for (size_t j = 0; j < subModels.size(); ++j) { - const cc::IntrusivePtr& subModel = subModels[j]; - + for (const auto& subModel : subModels) { const bool isTransparent = subModel->getPasses()->at(0)->getBlendState()->targets[0].blend; if (isTransparent) { continue; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 86e70d8a5a4..20820caed76 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -944,7 +944,7 @@ struct ProbeHelperQueue { void removeMacro() const; - int getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) const; + static int getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId); void applyMacro(const LayoutGraphData &lg, const cc::scene::Model& model, int probeLayoutId); }; From 749bc15676f18a5b3e16fe79b72f2f79460f4d0a Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Tue, 29 Aug 2023 16:37:37 +0800 Subject: [PATCH 39/82] Update --- native/cocos/renderer/pipeline/custom/NativePipeline.cpp | 2 +- native/cocos/renderer/pipeline/custom/NativePipelineTypes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index 737f2a05fae..2e2c21bf91c 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -747,7 +747,7 @@ namespace { auto* queueBuilder = passBuilder->addQueue(QueueHint::RENDER_OPAQUE, "reflect-map"); LightInfo lightInfo{}; lightInfo.probe = const_cast(probe); - queueBuilder->addSceneOfCamera(const_cast(probeCamera), lightInfo, SceneFlags::REFLECTION_PROBE | SceneFlags::OPAQUE_OBJECT); + queueBuilder->addSceneOfCamera(const_cast(camera), lightInfo, SceneFlags::REFLECTION_PROBE | SceneFlags::OPAQUE_OBJECT); updateCameraUBO(*queueBuilder, probeCamera, *pipeline); } diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 20820caed76..d2d83a550b7 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -934,7 +934,7 @@ struct DrawInstance { struct ProbeHelperQueue { ccstd::pmr::vector probeMap; - inline int getDefaultId(const LayoutGraphData &lg) const { + inline static int getDefaultId(const LayoutGraphData &lg) { return locate(locate(LayoutGraphData::null_vertex(), "default", lg), "default", lg); } From fa34683151fd8c2553b4420fd189d402eefdfd82 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 30 Aug 2023 13:49:46 +0800 Subject: [PATCH 40/82] add generated code --- cocos/rendering/custom/pipeline.ts | 7 +- .../pipeline/custom/NativePipelineFwd.h | 1 + .../pipeline/custom/NativePipelineTypes.cpp | 71 ++++--------------- .../pipeline/custom/NativePipelineTypes.h | 32 ++++++--- .../pipeline/custom/NativeRenderQueue.cpp | 69 ++++++++++++++++++ .../pipeline/custom/RenderCommonJsb.cpp | 3 - .../pipeline/custom/RenderCommonTypes.h | 4 +- 7 files changed, 109 insertions(+), 78 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 2d73357ff39..407053b7544 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -810,7 +810,10 @@ export interface BasicPipeline extends PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ addCopyPass (copyPairs: CopyPair[]): void; - addBuiltinReflectionProbePass (width: number, height: number, camera: Camera): void; + addBuiltinReflectionProbePass ( + width: number, + height: number, + camera: Camera): void; /** * @engineInternal */ @@ -1425,8 +1428,6 @@ export interface PipelineBuilder { * @param pipeline @en Current render pipeline @zh 当前管线 */ setup (cameras: Camera[], pipeline: BasicPipeline): void; - - onGlobalPipelineStateChanged?(): void; } /** diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 846d97ac32d..98fb163bf7c 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -51,6 +51,7 @@ class NativeComputeQueueBuilder; class NativeComputePassBuilder; struct RenderInstancingQueue; struct DrawInstance; +struct ProbeHelperQueue; struct RenderDrawQueue; struct NativeRenderQueue; struct ResourceGroup; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 336596af830..fdebe1a6c40 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -49,6 +49,15 @@ RenderInstancingQueue::RenderInstancingQueue(RenderInstancingQueue const& rhs, c passInstances(rhs.passInstances, alloc), instanceBuffers(rhs.instanceBuffers, alloc) {} +ProbeHelperQueue::ProbeHelperQueue(const allocator_type& alloc) noexcept +: probeMap(alloc) {} + +ProbeHelperQueue::ProbeHelperQueue(ProbeHelperQueue&& rhs, const allocator_type& alloc) +: probeMap(std::move(rhs.probeMap), alloc) {} + +ProbeHelperQueue::ProbeHelperQueue(ProbeHelperQueue const& rhs, const allocator_type& alloc) +: probeMap(rhs.probeMap, alloc) {} + RenderDrawQueue::RenderDrawQueue(const allocator_type& alloc) noexcept : instances(alloc) {} @@ -61,12 +70,14 @@ RenderDrawQueue::RenderDrawQueue(RenderDrawQueue const& rhs, const allocator_typ NativeRenderQueue::NativeRenderQueue(const allocator_type& alloc) noexcept : opaqueQueue(alloc), transparentQueue(alloc), + probeQueue(alloc), opaqueInstancingQueue(alloc), transparentInstancingQueue(alloc) {} NativeRenderQueue::NativeRenderQueue(SceneFlags sceneFlagsIn, uint32_t subpassOrPassLayoutIDIn, const allocator_type& alloc) noexcept : opaqueQueue(alloc), transparentQueue(alloc), + probeQueue(alloc), opaqueInstancingQueue(alloc), transparentInstancingQueue(alloc), sceneFlags(sceneFlagsIn), @@ -75,6 +86,7 @@ NativeRenderQueue::NativeRenderQueue(SceneFlags sceneFlagsIn, uint32_t subpassOr NativeRenderQueue::NativeRenderQueue(NativeRenderQueue&& rhs, const allocator_type& alloc) : opaqueQueue(std::move(rhs.opaqueQueue), alloc), transparentQueue(std::move(rhs.transparentQueue), alloc), + probeQueue(std::move(rhs.probeQueue), alloc), opaqueInstancingQueue(std::move(rhs.opaqueInstancingQueue), alloc), transparentInstancingQueue(std::move(rhs.transparentInstancingQueue), alloc), sceneFlags(rhs.sceneFlags), @@ -224,65 +236,6 @@ PipelineCustomization::PipelineCustomization(PipelineCustomization const& rhs, c renderQueues(rhs.renderQueues, alloc), renderCommands(rhs.renderCommands, alloc) {} -void ProbeHelperQueue::removeMacro() const -{ - for (auto* subModel : probeMap) { - std::vector patches; - patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); - - for (size_t j = 0; j < patches.size(); ++j) { - const cc::scene::IMacroPatch& patch = patches[j]; - if (patch.name == "CC_USE_RGBE_OUTPUT") { - patches.erase(patches.begin() + j); - break; - } - } - - subModel->onMacroPatchesStateChanged(patches); - } -} - -int ProbeHelperQueue::getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId) - { - const auto& passes = subModel->getPasses(); - for (size_t k = 0; k < passes->size(); ++k) { - if (passes->at(k)->getPhaseID() == phaseLayoutId) { - return static_cast(k); - } - } - return -1; -} - -void ProbeHelperQueue::applyMacro(const LayoutGraphData & lg, const cc::scene::Model & model, int probeLayoutId) -{ - const std::vector>& subModels = model.getSubModels(); - for (const auto& subModel : subModels) { - const bool isTransparent = subModel->getPasses()->at(0)->getBlendState()->targets[0].blend; - if (isTransparent) { - continue; - } - - int passIdx = getPassIndexFromLayout(subModel, probeLayoutId); - bool bUseReflectPass = true; - if (passIdx < 0) { - probeLayoutId = getDefaultId(lg); - passIdx = getPassIndexFromLayout(subModel, probeLayoutId); - bUseReflectPass = false; - } - if (passIdx < 0) { - continue; - } - if (!bUseReflectPass) { - std::vector patches; - patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); - const cc::scene::IMacroPatch useRGBEPatch = {"CC_USE_RGBE_OUTPUT", true}; - patches.emplace_back(useRGBEPatch); - subModel->onMacroPatchesStateChanged(patches); - probeMap.emplace_back(subModel); - } - } - } - } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index d2d83a550b7..a536bddf51f 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -41,7 +41,6 @@ #include "cocos/renderer/pipeline/custom/NativeTypes.h" #include "cocos/renderer/pipeline/custom/details/Map.h" #include "cocos/renderer/pipeline/custom/details/Set.h" -#include "LayoutGraphGraphs.h" #ifdef _MSC_VER #pragma warning(push) @@ -932,21 +931,33 @@ struct DrawInstance { }; struct ProbeHelperQueue { - ccstd::pmr::vector probeMap; - - inline static int getDefaultId(const LayoutGraphData &lg) { - return locate(locate(LayoutGraphData::null_vertex(), "default", lg), "default", lg); + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {probeMap.get_allocator().resource()}; } - inline void clear() { + ProbeHelperQueue(const allocator_type& alloc) noexcept; // NOLINT + ProbeHelperQueue(ProbeHelperQueue&& rhs, const allocator_type& alloc); + ProbeHelperQueue(ProbeHelperQueue const& rhs, const allocator_type& alloc); + + ProbeHelperQueue(ProbeHelperQueue&& rhs) noexcept = default; + ProbeHelperQueue(ProbeHelperQueue const& rhs) = delete; + ProbeHelperQueue& operator=(ProbeHelperQueue&& rhs) = default; + ProbeHelperQueue& operator=(ProbeHelperQueue const& rhs) = default; + + static LayoutGraphData::vertex_descriptor getDefaultId(const LayoutGraphData &lg); + + inline void clear() noexcept { probeMap.clear(); } void removeMacro() const; - static int getPassIndexFromLayout(const cc::IntrusivePtr& subModel, int phaseLayoutId); + static uint32_t getPassIndexFromLayout(const IntrusivePtr& subModel, LayoutGraphData::vertex_descriptor phaseLayoutId); + + void applyMacro(const LayoutGraphData &lg, const scene::Model& model, LayoutGraphData::vertex_descriptor probeLayoutId); - void applyMacro(const LayoutGraphData &lg, const cc::scene::Model& model, int probeLayoutId); + ccstd::pmr::vector probeMap; }; struct RenderDrawQueue { @@ -1175,8 +1186,8 @@ struct CullingKey { }; inline bool operator==(const CullingKey& lhs, const CullingKey& rhs) noexcept { - return std::forward_as_tuple(lhs.camera, lhs.light, lhs.castShadow, lhs.lightLevel) == - std::forward_as_tuple(rhs.camera, rhs.light, rhs.castShadow, rhs.lightLevel); + return std::forward_as_tuple(lhs.camera, lhs.light, lhs.probe, lhs.castShadow, lhs.lightLevel) == + std::forward_as_tuple(rhs.camera, rhs.light, rhs.probe, rhs.castShadow, rhs.lightLevel); } inline bool operator!=(const CullingKey& lhs, const CullingKey& rhs) noexcept { @@ -1489,6 +1500,7 @@ inline hash_t hash::operator()(const cc::render::Culling hash_t seed = 0; hash_combine(seed, val.camera); hash_combine(seed, val.light); + hash_combine(seed, val.probe); hash_combine(seed, val.castShadow); hash_combine(seed, val.lightLevel); return seed; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp index 3f95918ac34..ef9578039ef 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp @@ -27,12 +27,81 @@ #include "NativePipelineTypes.h" #include "cocos/renderer/pipeline/Define.h" #include "cocos/renderer/pipeline/PipelineStateManager.h" +#include "cocos/renderer/pipeline/custom/LayoutGraphGraphs.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" namespace cc { namespace render { +LayoutGraphData::vertex_descriptor ProbeHelperQueue::getDefaultId(const LayoutGraphData &lg) { + const auto passID = locate(LayoutGraphData::null_vertex(), "default", lg); + CC_ENSURES(passID != LayoutGraphData::null_vertex()); + auto phaseID = locate(passID, "default", lg); + CC_ENSURES(phaseID != LayoutGraphData::null_vertex()); + return phaseID; +} + +void ProbeHelperQueue::removeMacro() const { + for (auto *subModel : probeMap) { + std::vector patches; + patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); + + for (int j = 0; j != patches.size(); ++j) { + const cc::scene::IMacroPatch &patch = patches[j]; + if (patch.name == "CC_USE_RGBE_OUTPUT") { + patches.erase(patches.begin() + j); + break; + } + } + + subModel->onMacroPatchesStateChanged(patches); + } +} + +uint32_t ProbeHelperQueue::getPassIndexFromLayout( + const cc::IntrusivePtr &subModel, + LayoutGraphData::vertex_descriptor phaseLayoutId) { + const auto &passes = subModel->getPasses(); + for (uint32_t k = 0; k != passes->size(); ++k) { + if (passes->at(k)->getPhaseID() == phaseLayoutId) { + return static_cast(k); + } + } + return 0xFFFFFFFF; +} + +void ProbeHelperQueue::applyMacro( + const LayoutGraphData &lg, const cc::scene::Model &model, + LayoutGraphData::vertex_descriptor probeLayoutId) { + const std::vector> &subModels = model.getSubModels(); + for (const auto &subModel : subModels) { + const bool isTransparent = subModel->getPasses()->at(0)->getBlendState()->targets[0].blend; + if (isTransparent) { + continue; + } + + auto passIdx = getPassIndexFromLayout(subModel, probeLayoutId); + bool bUseReflectPass = true; + if (passIdx < 0) { + probeLayoutId = getDefaultId(lg); + passIdx = getPassIndexFromLayout(subModel, probeLayoutId); + bUseReflectPass = false; + } + if (passIdx < 0) { + continue; + } + if (!bUseReflectPass) { + std::vector patches; + patches.insert(patches.end(), subModel->getPatches().begin(), subModel->getPatches().end()); + const cc::scene::IMacroPatch useRGBEPatch = {"CC_USE_RGBE_OUTPUT", true}; + patches.emplace_back(useRGBEPatch); + subModel->onMacroPatchesStateChanged(patches); + probeMap.emplace_back(subModel); + } + } +} + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) void RenderDrawQueue::add(const scene::Model &model, float depth, uint32_t subModelIdx, uint32_t passIdx) { const auto *subModel = model.getSubModels()[subModelIdx].get(); diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp index 14d6dd41412..249ddbbd78c 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp @@ -50,9 +50,6 @@ bool nativevalue_to_se(const cc::render::LightInfo &from, se::Value &to, se::Obj nativevalue_to_se(from.culledByLight, tmp, ctx); obj->setProperty("culledByLight", tmp); - nativevalue_to_se(from.probe, tmp, ctx); - obj->setProperty("light", tmp); - to.setObject(obj); return true; } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index 91f8c5c6917..2054c2d314e 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -36,7 +36,6 @@ #include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/pipeline/custom/RenderCommonFwd.h" #include "cocos/scene/Light.h" -#include "cocos/scene/ReflectionProbe.h" namespace cc { @@ -226,8 +225,7 @@ struct LightInfo { : light(std::move(lightIn)), probe(probeIn), level(levelIn), - culledByLight(culledByLightIn) - {} + culledByLight(culledByLightIn) {} LightInfo(IntrusivePtr lightIn, uint32_t levelIn) noexcept : light(std::move(lightIn)), level(levelIn) {} From df20a520f7ce386e0e46abd5ad71cea7a6f4468a Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 30 Aug 2023 14:10:36 +0800 Subject: [PATCH 41/82] remove width and height --- cocos/rendering/custom/pipeline.ts | 5 +- .../pipeline/custom/NativePipeline.cpp | 188 +++++++++--------- .../pipeline/custom/NativePipelineTypes.h | 2 +- .../pipeline/custom/NativeRenderQueue.cpp | 2 +- .../pipeline/custom/RenderInterfaceTypes.h | 2 +- 5 files changed, 102 insertions(+), 97 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 407053b7544..b37be952b8a 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -810,10 +810,7 @@ export interface BasicPipeline extends PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ addCopyPass (copyPairs: CopyPair[]): void; - addBuiltinReflectionProbePass ( - width: number, - height: number, - camera: Camera): void; + addBuiltinReflectionProbePass (camera: Camera): void; /** * @engineInternal */ diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index 086e87d1e9e..ad31201328f 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -32,9 +32,12 @@ #include "cocos/renderer/pipeline/custom/RenderGraphGraphs.h" #include "cocos/renderer/pipeline/custom/RenderingModule.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" +#include "cocos/scene/ReflectionProbe.h" +#include "cocos/scene/ReflectionProbeManager.h" #include "cocos/scene/RenderScene.h" #include "cocos/scene/RenderWindow.h" -#include "cocos/scene/ReflectionProbeManager.h" +#include "pipeline/custom/RenderInterfaceTypes.h" + #if CC_USE_DEBUG_RENDERER #include "profiler/DebugRenderer.h" #endif @@ -43,14 +46,14 @@ namespace cc { namespace render { -template +template void addSubresourceNode(ResourceGraph::vertex_descriptor v, const ccstd::string &name, ResourceGraph &resg); template <> void addSubresourceNode(ResourceGraph::vertex_descriptor v, const ccstd::string &name, ResourceGraph &resg) { - const auto& desc = get(ResourceGraph::DescTag{}, resg, v); - const auto& traits = get(ResourceGraph::TraitsTag{}, resg, v); - const auto& samplerInfo = get(ResourceGraph::SamplerTag{}, resg, v); + const auto &desc = get(ResourceGraph::DescTag{}, resg, v); + const auto &traits = get(ResourceGraph::TraitsTag{}, resg, v); + const auto &samplerInfo = get(ResourceGraph::SamplerTag{}, resg, v); SubresourceView view{ nullptr, @@ -61,7 +64,6 @@ void addSubresourceNode(ResourceGraph::vertex_descri 1, // numArraySlices 0, // firstPlane 1, // numPlanes - desc.viewType, }; ccstd::string depthName{name}; @@ -315,7 +317,7 @@ uint32_t NativePipeline::addTexture(const ccstd::string &name, gfx::TextureType sampleCount, residency == ResourceResidency::MEMORYLESS ? gfx::TextureFlagBit::LAZILY_ALLOCATED : gfx::TextureFlagBit::NONE, flags, - type + type, }; return addVertex( ManagedTextureTag{}, @@ -352,15 +354,16 @@ void NativePipeline::updateBuffer(const ccstd::string &name, uint32_t size) { updateResource(name, gfx::Format::UNKNOWN, size, 0, 0, 0, 0, gfx::SampleCount::X1); } -uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimension dimension, +uint32_t NativePipeline::addResource( + const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) { - return dimension == ResourceDimension::BUFFER ? addBuffer(name, width, flags, residency) : - addTexture(name, getTextureType(dimension, arraySize), format, width, height, depth, arraySize, mipLevels, sampleCount, flags, residency); + return dimension == ResourceDimension::BUFFER ? addBuffer(name, width, flags, residency) : addTexture(name, getTextureType(dimension, arraySize), format, width, height, depth, arraySize, mipLevels, sampleCount, flags, residency); } -void NativePipeline::updateResource(const ccstd::string& name, gfx::Format format, +void NativePipeline::updateResource( + const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, // NOLINT(bugprone-easily-swappable-parameters) gfx::SampleCount sampleCount) { auto resID = findVertex(ccstd::pmr::string(name, get_allocator()), resourceGraph); @@ -391,7 +394,7 @@ void NativePipeline::updateResource(const ccstd::string& name, gfx::Format forma resourceGraph.invalidatePersistentRenderPassAndFramebuffer(tex.texture.get()); } }, - [&](ManagedBuffer &/*buffer*/) { + [&](ManagedBuffer & /*buffer*/) { desc.width = width; }, [](const auto & /*res*/) {}); @@ -408,7 +411,7 @@ uint32_t NativePipeline::addStorageTexture(const ccstd::string &name, gfx::Forma desc.format = format; desc.sampleCount = gfx::SampleCount::X1; desc.textureFlags = gfx::TextureFlagBit::NONE; - desc.flags = ResourceFlags::STORAGE | ResourceFlags::SAMPLED | ResourceFlags::TRANSFER_SRC | ResourceFlags::TRANSFER_DST;; + desc.flags = ResourceFlags::STORAGE | ResourceFlags::SAMPLED | ResourceFlags::TRANSFER_SRC | ResourceFlags::TRANSFER_DST; CC_EXPECTS(residency == ResourceResidency::MANAGED || residency == ResourceResidency::MEMORYLESS); @@ -687,85 +690,89 @@ void NativePipeline::endFrame() { namespace { - gfx::LoadOp getLoadOpOfClearFlag(gfx::ClearFlagBit clearFlag, AttachmentType attachment) { - gfx::LoadOp loadOp = gfx::LoadOp::CLEAR; - if (!(clearFlag & gfx::ClearFlagBit::COLOR) && attachment == AttachmentType::RENDER_TARGET) { - if (static_cast(clearFlag) & cc::scene::Camera::SKYBOX_FLAG) { - loadOp = gfx::LoadOp::CLEAR; - } else { - loadOp = gfx::LoadOp::LOAD; - } - } - if ((clearFlag & gfx::ClearFlagBit::DEPTH_STENCIL) != gfx::ClearFlagBit::DEPTH_STENCIL && attachment == AttachmentType::DEPTH_STENCIL) { - if (!(clearFlag & gfx::ClearFlagBit::DEPTH)) { - loadOp = gfx::LoadOp::LOAD; - } - if (!(clearFlag & gfx::ClearFlagBit::STENCIL)) { - loadOp = gfx::LoadOp::LOAD; - } +gfx::LoadOp getLoadOpOfClearFlag(gfx::ClearFlagBit clearFlag, AttachmentType attachment) { + gfx::LoadOp loadOp = gfx::LoadOp::CLEAR; + if (!(clearFlag & gfx::ClearFlagBit::COLOR) && attachment == AttachmentType::RENDER_TARGET) { + if (static_cast(clearFlag) & cc::scene::Camera::SKYBOX_FLAG) { + loadOp = gfx::LoadOp::CLEAR; + } else { + loadOp = gfx::LoadOp::LOAD; } - return loadOp; - } - void updateCameraUBO(Setter &setter, const scene::Camera *camera, NativePipeline &ppl) { - auto sceneData = ppl.pipelineSceneData; - auto* skybox = sceneData->getSkybox(); - setter.setBuiltinCameraConstants(camera); - } - void buildReflectionProbePass(const scene::Camera *camera, - render::NativePipeline *pipeline, - const scene::ReflectionProbe *probe, - scene::RenderWindow *renderWindow, - int faceIdx) { - const std::string cameraName = "Camera" + std::to_string(faceIdx); - const auto &area = probe->renderArea(); - int width = area.x; - int height = area.y; - const auto *probeCamera = probe->getCamera(); - const std::string probePassRTName = "reflectionProbePassColor" + cameraName; - const std::string probePassDSName = "reflectionProbePassDS" + cameraName; - if (!pipeline->containsResource(probePassRTName)) { - pipeline->addRenderWindow(probePassRTName, gfx::Format::RGBA8, width, height, renderWindow); - pipeline->addDepthStencil(probePassDSName, gfx::Format::DEPTH_STENCIL, width, height, ResourceResidency::EXTERNAL); + if ((clearFlag & gfx::ClearFlagBit::DEPTH_STENCIL) != gfx::ClearFlagBit::DEPTH_STENCIL && attachment == AttachmentType::DEPTH_STENCIL) { + if (!(clearFlag & gfx::ClearFlagBit::DEPTH)) { + loadOp = gfx::LoadOp::LOAD; + } + if (!(clearFlag & gfx::ClearFlagBit::STENCIL)) { + loadOp = gfx::LoadOp::LOAD; } - pipeline->updateRenderWindow(probePassRTName, renderWindow); - pipeline->updateDepthStencil(probePassDSName, width, height, gfx::Format::DEPTH_STENCIL); - auto *passBuilder = pipeline->addRenderPass(width, height, "default"); - passBuilder->setName("ReflectionProbePass"+faceIdx); - gfx::Viewport currViewport{}; - currViewport.width = width; - currViewport.height = height; - passBuilder->setViewport(currViewport); - gfx::Color clearColor{}; - clearColor.x = probeCamera->getClearColor().x; - clearColor.y = probeCamera->getClearColor().y; - clearColor.z = probeCamera->getClearColor().z; - clearColor.w = probeCamera->getClearColor().w; - passBuilder->addRenderTarget(probePassRTName, - getLoadOpOfClearFlag(probeCamera->getClearFlag(), AttachmentType::RENDER_TARGET), - gfx::StoreOp::STORE, - clearColor); - passBuilder->addDepthStencil(probePassDSName, - getLoadOpOfClearFlag(probeCamera->getClearFlag(), AttachmentType::DEPTH_STENCIL), - gfx::StoreOp::STORE, - probeCamera->getClearDepth(), - probeCamera->getClearStencil(), - probeCamera->getClearFlag()); - auto* queueBuilder = passBuilder->addQueue(QueueHint::RENDER_OPAQUE, "reflect-map"); - LightInfo lightInfo{}; - lightInfo.probe = const_cast(probe); - queueBuilder->addSceneOfCamera(const_cast(camera), lightInfo, SceneFlags::REFLECTION_PROBE | SceneFlags::OPAQUE_OBJECT); - updateCameraUBO(*queueBuilder, probeCamera, *pipeline); } + return loadOp; +} + +void updateCameraUBO(Setter &setter, const scene::Camera *camera, NativePipeline &ppl) { + auto sceneData = ppl.pipelineSceneData; + auto *skybox = sceneData->getSkybox(); + setter.setBuiltinCameraConstants(camera); +} + +void buildReflectionProbePass( + const scene::Camera *camera, + render::NativePipeline *pipeline, + const scene::ReflectionProbe *probe, + scene::RenderWindow *renderWindow, + int faceIdx) { + const std::string cameraName = "Camera" + std::to_string(faceIdx); + const auto &area = probe->renderArea(); + const auto width = static_cast(area.x); + const auto height = static_cast(area.y); + const auto *probeCamera = probe->getCamera(); + const std::string probePassRTName = "reflectionProbePassColor" + cameraName; + const std::string probePassDSName = "reflectionProbePassDS" + cameraName; + if (!pipeline->containsResource(probePassRTName)) { + pipeline->addRenderWindow(probePassRTName, gfx::Format::RGBA8, width, height, renderWindow); + pipeline->addDepthStencil(probePassDSName, gfx::Format::DEPTH_STENCIL, width, height, ResourceResidency::EXTERNAL); + } + pipeline->updateRenderWindow(probePassRTName, renderWindow); + pipeline->updateDepthStencil(probePassDSName, width, height, gfx::Format::DEPTH_STENCIL); + std::unique_ptr passBuilder(pipeline->addRenderPass(width, height, "default")); + passBuilder->setName("ReflectionProbePass" + std::to_string(faceIdx)); + gfx::Viewport currViewport{}; + currViewport.width = width; + currViewport.height = height; + passBuilder->setViewport(currViewport); + gfx::Color clearColor{}; + clearColor.x = probeCamera->getClearColor().x; + clearColor.y = probeCamera->getClearColor().y; + clearColor.z = probeCamera->getClearColor().z; + clearColor.w = probeCamera->getClearColor().w; + passBuilder->addRenderTarget( + probePassRTName, + getLoadOpOfClearFlag(probeCamera->getClearFlag(), AttachmentType::RENDER_TARGET), + gfx::StoreOp::STORE, + clearColor); + passBuilder->addDepthStencil( + probePassDSName, + getLoadOpOfClearFlag(probeCamera->getClearFlag(), AttachmentType::DEPTH_STENCIL), + gfx::StoreOp::STORE, + probeCamera->getClearDepth(), + probeCamera->getClearStencil(), + probeCamera->getClearFlag()); + std::unique_ptr queueBuilder( + passBuilder->addQueue(QueueHint::RENDER_OPAQUE, "reflect-map")); + LightInfo lightInfo{}; + lightInfo.probe = const_cast(probe); + queueBuilder->addSceneOfCamera(const_cast(camera), lightInfo, SceneFlags::REFLECTION_PROBE | SceneFlags::OPAQUE_OBJECT); + updateCameraUBO(*queueBuilder, probeCamera, *pipeline); +} } // namespace -void NativePipeline::addBuiltinReflectionProbePass( - uint32_t width, uint32_t height, const scene::Camera *camera) { - const auto* reflectProbeManager = scene::ReflectionProbeManager::getInstance(); +void NativePipeline::addBuiltinReflectionProbePass(const scene::Camera *camera) { + const auto *reflectProbeManager = scene::ReflectionProbeManager::getInstance(); if (!reflectProbeManager) return; const auto &probes = reflectProbeManager->getAllProbes(); - for (auto* probe : probes) { + for (auto *probe : probes) { if (probe->needRender()) { if (probe->getProbeType() == scene::ReflectionProbe::ProbeType::PLANAR) { buildReflectionProbePass(camera, this, probe, probe->getRealtimePlanarTexture()->getWindow(), 0); @@ -872,7 +879,7 @@ void NativePipeline::addMovePass(const ccstd::vector &movePairs) { namespace { void setupGpuDrivenResources( - NativePipeline& ppl, uint32_t cullingID, ResourceGraph& resg, const std::string &hzbName) { + NativePipeline &ppl, uint32_t cullingID, ResourceGraph &resg, const std::string &hzbName) { ccstd::pmr::string name(resg.get_allocator()); { // init resource name = "_GpuInit"; @@ -949,7 +956,6 @@ void setupGpuDrivenResources( } } if (!hzbName.empty()) { - } } @@ -984,7 +990,8 @@ void NativePipeline::addBuiltinGpuCullingPass( copyPass.copyPairs.emplace_back(std::move(copyPair)); } - auto copyID = addVertex2(CopyTag{}, + auto copyID = addVertex2( + CopyTag{}, std::forward_as_tuple("CopyInitialIndirectBuffer"), std::forward_as_tuple(), std::forward_as_tuple(), @@ -1001,7 +1008,7 @@ void NativePipeline::addBuiltinGpuCullingPass( std::piecewise_construct, std::forward_as_tuple(drawIndirectBuffer), std::forward_as_tuple()); - auto& view = res.first->second.emplace_back(); + auto &view = res.first->second.emplace_back(); view.name = "CCDrawIndirectBuffer"; view.accessType = AccessType::WRITE; view.shaderStageFlags = gfx::ShaderStageFlagBit::COMPUTE; @@ -1011,7 +1018,7 @@ void NativePipeline::addBuiltinGpuCullingPass( std::piecewise_construct, std::forward_as_tuple(drawInstanceBuffer), std::forward_as_tuple()); - auto& view = res.first->second.emplace_back(); + auto &view = res.first->second.emplace_back(); view.name = "CCDrawInstanceBuffer"; view.accessType = AccessType::WRITE; view.shaderStageFlags = gfx::ShaderStageFlagBit::COMPUTE; @@ -1021,13 +1028,14 @@ void NativePipeline::addBuiltinGpuCullingPass( std::piecewise_construct, std::forward_as_tuple(visibilityBuffer), std::forward_as_tuple()); - auto& view = res.first->second.emplace_back(); + auto &view = res.first->second.emplace_back(); view.name = "CCVisibilityBuffer"; view.accessType = AccessType::WRITE; view.shaderStageFlags = gfx::ShaderStageFlagBit::COMPUTE; } - auto computePassID = addVertex2(ComputeTag{}, + auto computePassID = addVertex2( + ComputeTag{}, std::forward_as_tuple("Scene"), std::forward_as_tuple(), std::forward_as_tuple(), diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index a536bddf51f..461a3ac19a1 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1408,7 +1408,7 @@ class NativePipeline final : public Pipeline { void endFrame() override; void addResolvePass(const ccstd::vector &resolvePairs) override; void addCopyPass(const ccstd::vector ©Pairs) override; - void addBuiltinReflectionProbePass(uint32_t width, uint32_t height, const scene::Camera *camera) override; + void addBuiltinReflectionProbePass(const scene::Camera *camera) override; gfx::DescriptorSetLayout *getDescriptorSetLayout(const ccstd::string &shaderName, UpdateFrequency freq) override; uint32_t addStorageBuffer(const ccstd::string &name, gfx::Format format, uint32_t size, ResourceResidency residency) override; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp index ef9578039ef..41525f49df2 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp @@ -37,7 +37,7 @@ namespace render { LayoutGraphData::vertex_descriptor ProbeHelperQueue::getDefaultId(const LayoutGraphData &lg) { const auto passID = locate(LayoutGraphData::null_vertex(), "default", lg); CC_ENSURES(passID != LayoutGraphData::null_vertex()); - auto phaseID = locate(passID, "default", lg); + const auto phaseID = locate(passID, "default", lg); CC_ENSURES(phaseID != LayoutGraphData::null_vertex()); return phaseID; } diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 9dce67da144..531886bda52 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -844,7 +844,7 @@ class BasicPipeline : public PipelineRuntime { * @param copyPairs @en Array of copy source and target @zh 拷贝来源与目标的数组 */ virtual void addCopyPass(const ccstd::vector ©Pairs) = 0; - virtual void addBuiltinReflectionProbePass(uint32_t width, uint32_t height, const scene::Camera *camera) = 0; + virtual void addBuiltinReflectionProbePass(const scene::Camera *camera) = 0; /** * @engineInternal */ From a6465b7e8f3a2f0f03733e9950e8f15613da7196 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 30 Aug 2023 14:35:00 +0800 Subject: [PATCH 42/82] fix missing header --- .../renderer/pipeline/custom/NativeSceneCulling.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index a9f76757b7c..ceab894b7ac 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -1,12 +1,13 @@ +#include "cocos/renderer/pipeline/Define.h" #include "cocos/renderer/pipeline/custom/NativePipelineTypes.h" #include "cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" #include "cocos/renderer/pipeline/custom/details/Range.h" #include "cocos/scene/Octree.h" +#include "cocos/scene/ReflectionProbe.h" #include "cocos/scene/RenderScene.h" #include "cocos/scene/Skybox.h" #include "cocos/scene/SpotLight.h" -#include "cocos/renderer/pipeline/Define.h" namespace cc { @@ -203,8 +204,8 @@ void bruteForceCulling( // filter model by view visibility if (isNodeVisible(model.getNode(), visibility) || isModelVisible(model, visibility)) { // frustum culling - if ((!probe && isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) - || (probe && isIntersectAABB(*model.getWorldBounds(), *probe->getBoundingBox()))) { + if ((!probe && isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) || + (probe && isIntersectAABB(*model.getWorldBounds(), *probe->getBoundingBox()))) { continue; } @@ -362,7 +363,7 @@ void addRenderObject( const auto passCount = passes.size(); auto probeIt = std::find(queue.probeQueue.probeMap.begin(), queue.probeQueue.probeMap.end(), subModel.get()); if (probeIt != queue.probeQueue.probeMap.end()) { - phaseLayoutID = queue.probeQueue.getDefaultId(*layoutGraph); + phaseLayoutID = ProbeHelperQueue::getDefaultId(*layoutGraph); } for (uint32_t passIdx = 0; passIdx < passCount; ++passIdx) { auto& pass = *passes[passIdx]; From 94dd7be4afa8229ca192eac38b761ab6133b3ae9 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 30 Aug 2023 14:42:12 +0800 Subject: [PATCH 43/82] add missing web change --- cocos/rendering/custom/web-pipeline.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 0b4c9c310c7..9f915f40c35 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -2017,7 +2017,7 @@ export class WebPipeline implements BasicPipeline { this.execute(); this.endFrame(); } - addBuiltinReflectionProbePass (width: number, height: number, camera: Camera): void { + addBuiltinReflectionProbePass (camera: Camera): void { const reflectionProbeManager = cclegacy.internal.reflectionProbeManager as ReflectionProbeManager; if (!reflectionProbeManager) return; const probes = reflectionProbeManager.getProbes(); From 24d124d9af163e66e35682b2191885dd7e4fbdbd Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 30 Aug 2023 14:47:35 +0800 Subject: [PATCH 44/82] add missing change --- cocos/rendering/post-process/post-process-builder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index 15ba0a9c3ea..9d3b8a06b29 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -185,7 +185,7 @@ export class PostProcessBuilder implements PipelineBuilder { this.applyPreviewCamera(camera); } - ppl.addBuiltinReflectionProbePass(0, 0, camera); + ppl.addBuiltinReflectionProbePass(camera); passContext.postProcess = camera.postProcess || globalPP; From b5c272aa98d9207e4affda59f2fb61b91b63371a Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 31 Aug 2023 15:09:11 +0800 Subject: [PATCH 45/82] Replace old pipeline (#168) * Replace old pipeline * Update --- editor/engine-features/render-config.json | 3 ++- exports/custom-pipeline.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/editor/engine-features/render-config.json b/editor/engine-features/render-config.json index 59f4a6093b9..c7384057019 100644 --- a/editor/engine-features/render-config.json +++ b/editor/engine-features/render-config.json @@ -263,7 +263,8 @@ "default": [], "label": "i18n:ENGINE.features.custom_pipeline.label", "description": "i18n:ENGINE.features.custom_pipeline.description", - "wechatPlugin": false + "wechatPlugin": false, + "required": true } }, "categories": { diff --git a/exports/custom-pipeline.ts b/exports/custom-pipeline.ts index d3cfd957dd0..1692bf1f7e8 100644 --- a/exports/custom-pipeline.ts +++ b/exports/custom-pipeline.ts @@ -1,8 +1,11 @@ import { legacyCC } from '../cocos/core/global-exports'; +import { macro } from '../cocos/core/platform'; import * as rendering from '../cocos/rendering/custom'; import * as postProcess from '../cocos/rendering/post-process'; export { rendering }; export { postProcess }; +macro.CUSTOM_PIPELINE_NAME = 'Forward'; + legacyCC.rendering = rendering; From bcf72ba307eefd3cc2086e09e682d1476ad763f3 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 31 Aug 2023 16:07:25 +0800 Subject: [PATCH 46/82] Revert "Replace old pipeline (#168)" This reverts commit b5c272aa98d9207e4affda59f2fb61b91b63371a. # Conflicts: # editor/engine-features/render-config.json --- editor/engine-features/render-config.json | 1 - exports/custom-pipeline.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/editor/engine-features/render-config.json b/editor/engine-features/render-config.json index d2cfa831f33..1e1f468623a 100644 --- a/editor/engine-features/render-config.json +++ b/editor/engine-features/render-config.json @@ -292,7 +292,6 @@ "label": "i18n:ENGINE.features.custom_pipeline.label", "description": "i18n:ENGINE.features.custom_pipeline.description", "wechatPlugin": false, - "required": true, "taobaoMinigamePlugin": false } }, diff --git a/exports/custom-pipeline.ts b/exports/custom-pipeline.ts index 1692bf1f7e8..d3cfd957dd0 100644 --- a/exports/custom-pipeline.ts +++ b/exports/custom-pipeline.ts @@ -1,11 +1,8 @@ import { legacyCC } from '../cocos/core/global-exports'; -import { macro } from '../cocos/core/platform'; import * as rendering from '../cocos/rendering/custom'; import * as postProcess from '../cocos/rendering/post-process'; export { rendering }; export { postProcess }; -macro.CUSTOM_PIPELINE_NAME = 'Forward'; - legacyCC.rendering = rendering; From fd7368d9422dc9c32e473eea80705965b427d74b Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 1 Sep 2023 12:02:31 +0800 Subject: [PATCH 47/82] [Fixed] the problem that the wireframe is not displayed (#170) --- cocos/rendering/custom/scene-culling.ts | 7 ++++--- .../cocos/renderer/pipeline/custom/NativeSceneCulling.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 3753430b403..9c317488415 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -157,7 +157,7 @@ function sceneCulling ( for (const model of scene.models) { assert(!!model); - if (!model.enabled || !model.node || !model.worldBounds || (castShadow && !model.castShadow)) { + if (!model.enabled || !model.node || (castShadow && !model.castShadow)) { continue; } if (scene && scene.isCulledByLod(camera, model)) { @@ -166,9 +166,10 @@ function sceneCulling ( if (!probe || (probe && probe.probeType === ProbeType.CUBE)) { if (isNodeVisible(model.node, visibility) || isModelVisible(model, visibility)) { + const wBounds = model.worldBounds; // frustum culling - if ((!probe && isFrustumVisible(model, camOrLightFrustum, castShadow)) - || (probe && isIntersectAABB(model.worldBounds, probe.boundingBox!))) { + if (wBounds && ((!probe && isFrustumVisible(model, camOrLightFrustum, castShadow)) + || (probe && isIntersectAABB(wBounds, probe.boundingBox!)))) { continue; } diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index ceab894b7ac..b106ede8679 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -193,7 +193,7 @@ void bruteForceCulling( for (const auto& pModel : scene.getModels()) { CC_EXPECTS(pModel); const auto& model = *pModel; - if (!model.isEnabled() || !model.getNode() || !model.getWorldBounds() || (bCastShadow && !model.isCastShadow())) { + if (!model.isEnabled() || !model.getNode() || (bCastShadow && !model.isCastShadow())) { continue; } // lod culling @@ -203,9 +203,10 @@ void bruteForceCulling( if (!probe || (probe && probe->getProbeType() == cc::scene::ReflectionProbe::ProbeType::CUBE)) { // filter model by view visibility if (isNodeVisible(model.getNode(), visibility) || isModelVisible(model, visibility)) { + const auto* const wBounds = model.getWorldBounds(); // frustum culling - if ((!probe && isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) || - (probe && isIntersectAABB(*model.getWorldBounds(), *probe->getBoundingBox()))) { + if (wBounds && ((!probe && isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) || + (probe && isIntersectAABB(*wBounds, *probe->getBoundingBox())))) { continue; } From 1c8ae59c950e046e6a0564d6e7ecd8fc867b6666 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 1 Sep 2023 14:49:26 +0800 Subject: [PATCH 48/82] adding builtin lights --- .../pipeline/custom/NativeExecutor.cpp | 20 +++++--- .../renderer/pipeline/custom/NativeSetter.cpp | 47 +++++++++++++++++++ .../renderer/pipeline/custom/NativeUtils.h | 4 ++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index da02b3a9200..9ebb7d14c6a 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -60,6 +60,7 @@ namespace { constexpr uint32_t INVALID_ID = 0xFFFFFFFF; constexpr gfx::Color RASTER_COLOR{0.0, 1.0, 0.0, 1.0}; +constexpr gfx::Color RASTER_UPLOAD_COLOR{1.0, 1.0, 0.0, 1.0}; constexpr gfx::Color RENDER_QUEUE_COLOR{0.0, 0.5, 0.5, 1.0}; constexpr gfx::Color COMPUTE_COLOR{0.0, 0.0, 1.0, 1.0}; @@ -1124,9 +1125,6 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } } void begin(const RasterPass& pass, RenderGraph::vertex_descriptor vertID) const { -#if CC_DEBUG - ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RASTER_COLOR)); -#endif const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); if (!renderData.custom.empty()) { const auto& passes = ctx.ppl->custom.renderPasses; @@ -1484,10 +1482,6 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { ctx.cmdBuff->endRenderPass(); ctx.currentPass = nullptr; ctx.currentPassLayoutID = LayoutGraphData::null_vertex(); - -#if CC_DEBUG - ctx.cmdBuff->endMarker(); -#endif } void end(const RasterSubpass& subpass, RenderGraph::vertex_descriptor vertID) const { // NOLINT(readability-convert-member-functions-to-static) const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); @@ -1679,6 +1673,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { visitObject( vertID, ctx.g, [&](const RasterPass& pass) { +#if CC_DEBUG + ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RASTER_COLOR)); +#endif mountResources(pass); { const auto& layoutName = get(RenderGraph::LayoutTag{}, ctx.g, vertID); @@ -1687,9 +1684,15 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } // update UniformBuffers and DescriptorSets in all children { +#if CC_DEBUG + ctx.cmdBuff->beginMarker(makeMarkerInfo("Upload", RASTER_UPLOAD_COLOR)); +#endif auto colors = ctx.g.colors(ctx.scratch); RenderGraphUploadVisitor visitor{{}, ctx}; boost::depth_first_visit(gv, vertID, visitor, get(colors, ctx.g)); +#if CC_DEBUG + ctx.cmdBuff->endMarker(); +#endif } if (pass.showStatistics) { const auto* profiler = ctx.ppl->getProfiler(); @@ -1795,6 +1798,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { [&](const RasterPass& pass) { end(pass, vertID); rearBarriers(vertID); +#if CC_DEBUG + ctx.cmdBuff->endMarker(); +#endif }, [&](const RasterSubpass& subpass) { end(subpass, vertID); diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index bb313d6cfca..3fa33ea6a81 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -26,6 +26,7 @@ #include "cocos/renderer/pipeline/custom/NativePipelineTypes.h" #include "cocos/renderer/pipeline/custom/NativeUtils.h" #include "cocos/renderer/pipeline/custom/RenderGraphGraphs.h" +#include "cocos/scene/Light.h" #include "cocos/scene/RenderScene.h" #include "cocos/scene/SpotLight.h" @@ -148,6 +149,12 @@ void NativeSetter::setBuiltinShadowMapConstants( setShadowUBOView(*device, *layoutGraph, sceneData, *light, data); } +namespace { + +constexpr float LIGHT_METER_SCALE = 10000.0F; + +} // namespace + void NativeSetter::setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) { } @@ -155,6 +162,46 @@ void NativeSetter::setBuiltinSphereLightConstants(const scene::SphereLight *ligh } void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) { + const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); + const auto &shadowInfo = *sceneData.getShadows(); + + auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); + + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::SPOT))); + + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; + } else { + color.w = light->getLuminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + light->getSize(), + light->getRange(), + light->getSpotAngle(), + shadowInfo.isEnabled() && + light->isShadowEnabled() && + shadowInfo.getType() == scene::ShadowType::SHADOW_MAP + ? 1.0F + : 0.0F)); + + setVec4Impl( + data, *layoutGraph, "cc_lightDir", + toVec4(light->getDirection())); } void NativeSetter::setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) { diff --git a/native/cocos/renderer/pipeline/custom/NativeUtils.h b/native/cocos/renderer/pipeline/custom/NativeUtils.h index 82595dc3c92..efb11555b62 100644 --- a/native/cocos/renderer/pipeline/custom/NativeUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeUtils.h @@ -75,6 +75,10 @@ void setReadWriteTextureImpl(RenderData &data, const LayoutGraphData &lg, const void setSamplerImpl(RenderData &data, const LayoutGraphData &lg, const ccstd::string &name, gfx::Sampler *sampler); +inline Vec4 toVec4(const Vec3 &vec, float w = 0.0F) noexcept { + return {vec.x, vec.y, vec.z, w}; +} + } // namespace render } // namespace cc From 81e82bc6c0de37b31ce6d14969130f20c2dd9b0c Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 1 Sep 2023 17:48:26 +0800 Subject: [PATCH 49/82] adding culling --- cocos/rendering/custom/render-graph.ts | 28 +++++++++++-- .../pipeline/custom/NativeBuiltinUtils.h | 3 ++ .../pipeline/custom/NativePipelineFwd.h | 17 +++++++- .../pipeline/custom/NativePipelineTypes.h | 15 ++++--- .../pipeline/custom/NativeRenderGraph.cpp | 42 ++++++++++++++----- .../pipeline/custom/NativeSceneCulling.cpp | 6 +-- .../renderer/pipeline/custom/NativeUtils.h | 3 ++ .../renderer/pipeline/custom/PrivateFwd.h | 1 - .../pipeline/custom/RenderCommonFwd.h | 1 - .../renderer/pipeline/custom/RenderGraphFwd.h | 4 +- .../pipeline/custom/RenderGraphTypes.h | 37 +++++++++++++++- .../pipeline/custom/RenderInterfaceFwd.h | 3 -- 12 files changed, 127 insertions(+), 33 deletions(-) diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index eafbb37186f..735d113b675 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -1494,23 +1494,44 @@ export class RenderQueue { viewport: Viewport | null = null; } +export enum CullingFlags { + NONE = 0, + CAMERA_FRUSTUM = 0x1, + LIGHT_FRUSTUM = 0x2, + LIGHT_BOUNDS = 0x4, +} + export class SceneData { - constructor (scene: RenderScene | null = null, camera: Camera | null = null, flags: SceneFlags = SceneFlags.NONE, light: LightInfo = new LightInfo()) { + constructor ( + scene: RenderScene | null = null, + camera: Camera | null = null, + flags: SceneFlags = SceneFlags.NONE, + light: LightInfo = new LightInfo(), + cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, + ) { this.scene = scene; this.camera = camera; this.light = light; this.flags = flags; + this.cullingFlags = cullingFlags; } - reset (scene: RenderScene | null = null, camera: Camera | null = null, flags: SceneFlags = SceneFlags.NONE): void { + reset ( + scene: RenderScene | null = null, + camera: Camera | null = null, + flags: SceneFlags = SceneFlags.NONE, + cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, + ): void { this.scene = scene; this.camera = camera; this.light.reset(); this.flags = flags; + this.cullingFlags = cullingFlags; } /*pointer*/ scene: RenderScene | null; /*pointer*/ camera: Camera | null; readonly light: LightInfo; flags: SceneFlags; + cullingFlags: CullingFlags; } export class Dispatch { @@ -2776,9 +2797,10 @@ export class RenderGraphObjectPool { scene: RenderScene | null = null, camera: Camera | null = null, flags: SceneFlags = SceneFlags.NONE, + cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, ): SceneData { const v = this._sceneData.add(); - v.reset(scene, camera, flags); + v.reset(scene, camera, flags, cullingFlags); return v; } createDispatch ( diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h index b123a5332ac..e3f316085f2 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h @@ -24,6 +24,8 @@ #pragma once #include +#include "cocos/math/Vec4.h" +#include "cocos/renderer/gfx-base/GFXDevice.h" #include "cocos/renderer/pipeline/custom/LayoutGraphFwd.h" #include "cocos/renderer/pipeline/custom/NativeFwd.h" #include "cocos/renderer/pipeline/custom/RenderGraphFwd.h" @@ -32,6 +34,7 @@ namespace cc { namespace scene { class Camera; +class Light; class DirectionalLight; } // namespace scene diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 98fb163bf7c..903eeb19a50 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -29,13 +29,23 @@ */ // clang-format off #pragma once -#include "cocos/base/std/hash/hash.h" #include "cocos/base/std/variant.h" -#include "cocos/renderer/pipeline/InstancedBuffer.h" #include "cocos/renderer/pipeline/custom/NativeFwd.h" namespace cc { +namespace scene { + +class ReflectionProbe; + +} // namespace scene + +} // namespace cc + +#include "cocos/base/std/hash/hash.h" + +namespace cc { + namespace render { class NativeRenderNode; @@ -65,6 +75,9 @@ struct QuadResource; enum class ResourceType; struct SceneResource; + +using CullingTarget = ccstd::variant; + struct CullingKey; struct CullingQueries; struct NativeRenderQueueDesc; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 461a3ac19a1..b843ae7314c 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -41,6 +41,7 @@ #include "cocos/renderer/pipeline/custom/NativeTypes.h" #include "cocos/renderer/pipeline/custom/details/Map.h" #include "cocos/renderer/pipeline/custom/details/Set.h" +#include "cocos/scene/ReflectionProbe.h" #ifdef _MSC_VER #pragma warning(push) @@ -1177,17 +1178,19 @@ struct SceneResource { ccstd::pmr::unordered_map> storageImages; }; +using CullingTarget = ccstd::variant; + struct CullingKey { const scene::Camera* camera{nullptr}; - const scene::Light* light{nullptr}; const scene::ReflectionProbe* probe{nullptr}; - bool castShadow{false}; + const scene::Light* light{nullptr}; uint32_t lightLevel{0xFFFFFFFF}; + bool castShadow{false}; }; inline bool operator==(const CullingKey& lhs, const CullingKey& rhs) noexcept { - return std::forward_as_tuple(lhs.camera, lhs.light, lhs.probe, lhs.castShadow, lhs.lightLevel) == - std::forward_as_tuple(rhs.camera, rhs.light, rhs.probe, rhs.castShadow, rhs.lightLevel); + return std::forward_as_tuple(lhs.camera, lhs.probe, lhs.light, lhs.lightLevel, lhs.castShadow) == + std::forward_as_tuple(rhs.camera, rhs.probe, rhs.light, rhs.lightLevel, rhs.castShadow); } inline bool operator!=(const CullingKey& lhs, const CullingKey& rhs) noexcept { @@ -1499,10 +1502,10 @@ namespace ccstd { inline hash_t hash::operator()(const cc::render::CullingKey& val) const noexcept { hash_t seed = 0; hash_combine(seed, val.camera); - hash_combine(seed, val.light); hash_combine(seed, val.probe); - hash_combine(seed, val.castShadow); + hash_combine(seed, val.light); hash_combine(seed, val.lightLevel); + hash_combine(seed, val.castShadow); return seed; } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 960cb08d0d4..07a18b68f0f 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -50,8 +50,8 @@ void NativeRenderNode::setCustomBehavior(const ccstd::string &name) { // NOLINT( RenderGraph::vertex_descriptor RenderGraph::getPassID(vertex_descriptor nodeID) const { CC_EXPECTS(nodeID != null_vertex()); for (auto parentID = nodeID; - parentID != RenderGraph::null_vertex(); - parentID = parent(nodeID, *this)) { + parentID != RenderGraph::null_vertex(); + parentID = parent(nodeID, *this)) { nodeID = parentID; } CC_ENSURES(nodeID != null_vertex()); @@ -690,10 +690,27 @@ ComputeQueueBuilder *NativeComputeSubpassBuilder::addQueue(const ccstd::string & return new NativeComputeQueueBuilder(pipelineRuntime, renderGraph, queueID, layoutGraph, phaseLayoutID); } +namespace { + +CullingFlags makeCullingFlags(const LightInfo &light) { + auto cullingFlags = CullingFlags::NONE; + if (light.culledByLight) { + cullingFlags |= CullingFlags::LIGHT_FRUSTUM; + } else { + cullingFlags |= CullingFlags::CAMERA_FRUSTUM; + if (light.light) { + cullingFlags |= CullingFlags::LIGHT_BOUNDS; + } + } + return cullingFlags; +} + +} // namespace + void NativeRenderQueueBuilder::addSceneOfCamera( scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) { const auto *pLight = light.light.get(); - SceneData scene(camera->getScene(), camera, sceneFlags, light); + SceneData scene(camera->getScene(), camera, sceneFlags, light, makeCullingFlags(light)); auto sceneID = addVertex2( SceneTag{}, std::forward_as_tuple("Camera"), @@ -737,8 +754,11 @@ void NativeRenderQueueBuilder::addSceneOfCamera( } void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { - std::ignore = light; - SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{}); + auto cullingFlags = CullingFlags::CAMERA_FRUSTUM; + if (light) { + cullingFlags |= CullingFlags::LIGHT_BOUNDS; + } + SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{}, cullingFlags); auto sceneID = addVertex2( SceneTag{}, @@ -752,7 +772,7 @@ void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags if (any(sceneFlags & SceneFlags::GPU_DRIVEN)) { const auto passID = renderGraph->getPassID(nodeID); - const auto cullingID = dynamic_cast(pipelineRuntime)->nativeContext.sceneCulling.gpuCullingPassID; + const auto cullingID = dynamic_cast(pipelineRuntime)->nativeContext.sceneCulling.gpuCullingPassID; CC_EXPECTS(cullingID != 0xFFFFFFFF); if (holds(passID, *renderGraph)) { ccstd::pmr::string drawIndirectBuffer("CCDrawIndirectBuffer"); @@ -760,14 +780,14 @@ void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags ccstd::pmr::string drawInstanceBuffer("CCDrawInstanceBuffer"); drawInstanceBuffer.append(std::to_string(cullingID)); - auto& rasterPass = get(RasterPassTag{}, passID, *renderGraph); + auto &rasterPass = get(RasterPassTag{}, passID, *renderGraph); if (rasterPass.computeViews.find(drawIndirectBuffer) != rasterPass.computeViews.end()) { auto res = rasterPass.computeViews.emplace( std::piecewise_construct, std::forward_as_tuple(drawIndirectBuffer), std::forward_as_tuple()); CC_ENSURES(res.second); - auto& view = res.first->second.emplace_back(); + auto &view = res.first->second.emplace_back(); view.name = "CCDrawIndirectBuffer"; view.accessType = AccessType::READ; view.shaderStageFlags = gfx::ShaderStageFlagBit::VERTEX | gfx::ShaderStageFlagBit::FRAGMENT; @@ -778,7 +798,7 @@ void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags std::forward_as_tuple(drawInstanceBuffer), std::forward_as_tuple()); CC_ENSURES(res.second); - auto& view = res.first->second.emplace_back(); + auto &view = res.first->second.emplace_back(); view.name = "CCDrawInstanceBuffer"; view.accessType = AccessType::READ; view.shaderStageFlags = gfx::ShaderStageFlagBit::VERTEX | gfx::ShaderStageFlagBit::FRAGMENT; @@ -792,7 +812,7 @@ void NativeRenderQueueBuilder::addSceneCulledByDirectionalLight( scene::DirectionalLight *light, uint32_t level) { CC_EXPECTS(light); CC_EXPECTS(light->getType() != scene::LightType::UNKNOWN); - SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{light, level}); + SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{light, level}, CullingFlags::LIGHT_FRUSTUM); auto sceneID = addVertex2( SceneTag{}, @@ -810,7 +830,7 @@ void NativeRenderQueueBuilder::addSceneCulledBySpotLight( scene::SpotLight *light) { CC_EXPECTS(light); CC_EXPECTS(light->getType() != scene::LightType::UNKNOWN); - SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{light, 0}); + SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{light, 0}, CullingFlags::LIGHT_FRUSTUM); auto sceneID = addVertex2( SceneTag{}, diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index b106ede8679..b378e0eed8e 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -42,10 +42,10 @@ uint32_t SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sceneData) // make query key const auto key = CullingKey{ sceneData.camera, - sceneData.light.light, sceneData.light.probe, - bCastShadow, + sceneData.light.light, sceneData.light.level, + bCastShadow, }; // find query source @@ -206,7 +206,7 @@ void bruteForceCulling( const auto* const wBounds = model.getWorldBounds(); // frustum culling if (wBounds && ((!probe && isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) || - (probe && isIntersectAABB(*wBounds, *probe->getBoundingBox())))) { + (probe && isIntersectAABB(*wBounds, *probe->getBoundingBox())))) { continue; } diff --git a/native/cocos/renderer/pipeline/custom/NativeUtils.h b/native/cocos/renderer/pipeline/custom/NativeUtils.h index efb11555b62..83a11227a36 100644 --- a/native/cocos/renderer/pipeline/custom/NativeUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeUtils.h @@ -24,7 +24,10 @@ #pragma once #include "cocos/core/ArrayBuffer.h" +#include "cocos/math/Vec2.h" +#include "cocos/math/Vec3.h" #include "cocos/math/Vec4.h" +#include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/pipeline/custom/LayoutGraphFwd.h" #include "cocos/renderer/pipeline/custom/RenderGraphFwd.h" #include "cocos/renderer/pipeline/custom/RenderInterfaceFwd.h" diff --git a/native/cocos/renderer/pipeline/custom/PrivateFwd.h b/native/cocos/renderer/pipeline/custom/PrivateFwd.h index 9bdfb3b4e7d..5c6f8fc2802 100644 --- a/native/cocos/renderer/pipeline/custom/PrivateFwd.h +++ b/native/cocos/renderer/pipeline/custom/PrivateFwd.h @@ -30,7 +30,6 @@ // clang-format off #pragma once #include "cocos/base/std/variant.h" -#include "cocos/renderer/core/ProgramLib.h" #include "cocos/renderer/pipeline/custom/RenderInterfaceFwd.h" namespace cc { diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonFwd.h b/native/cocos/renderer/pipeline/custom/RenderCommonFwd.h index 1628d725ef7..929719b046a 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonFwd.h @@ -31,7 +31,6 @@ #pragma once #include "cocos/base/std/hash/hash.h" #include "cocos/base/std/variant.h" -#include "cocos/renderer/gfx-base/GFXDef-common.h" namespace cc { diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h b/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h index 0ec6698a935..09e8106431a 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h @@ -32,7 +32,6 @@ #include "cocos/base/std/hash/hash.h" #include "cocos/base/std/variant.h" #include "cocos/renderer/pipeline/custom/RenderCommonFwd.h" -#include "cocos/scene/Camera.h" namespace cc { @@ -80,6 +79,9 @@ struct ClearTag; struct ViewportTag; struct ClearView; struct RenderQueue; + +enum class CullingFlags : uint32_t; + struct SceneData; struct Dispatch; struct Blit; diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h index 2ab46b7bdab..2a6db6b7445 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h @@ -848,18 +848,51 @@ struct RenderQueue { gfx::Viewport viewport; }; +enum class CullingFlags : uint32_t { + NONE = 0, + CAMERA_FRUSTUM = 0x1, + LIGHT_FRUSTUM = 0x2, + LIGHT_BOUNDS = 0x4, +}; + +constexpr CullingFlags operator|(const CullingFlags lhs, const CullingFlags rhs) noexcept { + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +constexpr CullingFlags operator&(const CullingFlags lhs, const CullingFlags rhs) noexcept { + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +constexpr CullingFlags& operator|=(CullingFlags& lhs, const CullingFlags rhs) noexcept { + return lhs = lhs | rhs; +} + +constexpr CullingFlags& operator&=(CullingFlags& lhs, const CullingFlags rhs) noexcept { + return lhs = lhs & rhs; +} + +constexpr bool operator!(CullingFlags e) noexcept { + return e == static_cast(0); +} + +constexpr bool any(CullingFlags e) noexcept { + return !!e; +} + struct SceneData { SceneData() = default; - SceneData(const scene::RenderScene* sceneIn, const scene::Camera* cameraIn, SceneFlags flagsIn, LightInfo lightIn) noexcept + SceneData(const scene::RenderScene* sceneIn, const scene::Camera* cameraIn, SceneFlags flagsIn, LightInfo lightIn, CullingFlags cullingFlagsIn) noexcept : scene(sceneIn), camera(cameraIn), light(std::move(lightIn)), - flags(flagsIn) {} + flags(flagsIn), + cullingFlags(cullingFlagsIn) {} const scene::RenderScene* scene{nullptr}; const scene::Camera* camera{nullptr}; LightInfo light; SceneFlags flags{SceneFlags::NONE}; + CullingFlags cullingFlags{CullingFlags::CAMERA_FRUSTUM}; }; struct Dispatch { diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h index 7a72a5f60e8..ee0505f07f2 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h @@ -30,9 +30,6 @@ // clang-format off #pragma once #include "cocos/base/std/variant.h" -#include "cocos/core/assets/EffectAsset.h" -#include "cocos/renderer/core/PassUtils.h" -#include "cocos/renderer/pipeline/PipelineSceneData.h" #include "cocos/renderer/pipeline/custom/CustomFwd.h" namespace cc { From 93b189528c7b6364c3041b6a5b5378fd9182ab2a Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Wed, 6 Sep 2023 15:06:20 +0800 Subject: [PATCH 50/82] Update (#169) --- cocos/rendering/scene-culling.ts | 2 +- native/cocos/renderer/pipeline/SceneCulling.cpp | 3 ++- native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cocos/rendering/scene-culling.ts b/cocos/rendering/scene-culling.ts index ca507ed247e..64173902a93 100644 --- a/cocos/rendering/scene-culling.ts +++ b/cocos/rendering/scene-culling.ts @@ -41,7 +41,7 @@ const roPool = new Pool((): IRenderObject => ({ model: null!, dep function getRenderObject (model: Model, camera: Camera): IRenderObject { let depth = 0; if (model.node) { - Vec3.subtract(_tempVec3, model.node.worldPosition, camera.position); + Vec3.subtract(_tempVec3, model.worldBounds ? model.worldBounds.center : model.node.worldPosition, camera.position); depth = Vec3.dot(_tempVec3, camera.forward); } const ro = roPool.alloc(); diff --git a/native/cocos/renderer/pipeline/SceneCulling.cpp b/native/cocos/renderer/pipeline/SceneCulling.cpp index 46babac15dc..d94ad2cb40e 100644 --- a/native/cocos/renderer/pipeline/SceneCulling.cpp +++ b/native/cocos/renderer/pipeline/SceneCulling.cpp @@ -57,7 +57,8 @@ RenderObject genRenderObject(const scene::Model *model, const scene::Camera *cam if (model->getNode()) { const auto *node = model->getTransform(); cc::Vec3 position; - cc::Vec3::subtract(node->getWorldPosition(), camera->getPosition(), &position); + const auto *bounds = model->getWorldBounds(); + Vec3::subtract(bounds ? bounds->center : node->getWorldPosition(), camera->getPosition(), &position); depth = position.dot(camera->getForward()); } diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index b378e0eed8e..70613e6b1d7 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -339,7 +339,8 @@ float computeSortingDepth(const scene::Camera& camera, const scene::Model& model if (model.getNode()) { const auto* node = model.getTransform(); Vec3 position; - Vec3::subtract(node->getWorldPosition(), camera.getPosition(), &position); + const auto* bounds = model.getWorldBounds(); + Vec3::subtract(bounds ? bounds->center : node->getWorldPosition(), camera.getPosition(), &position); depth = position.dot(camera.getForward()); } return depth; From 481d2702ac08a077f9370c182d37c9d40d120d8b Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 7 Sep 2023 16:25:07 +0800 Subject: [PATCH 51/82] enhance cullingID type safety --- .../pipeline/custom/NativeExecutor.cpp | 20 ++--- .../pipeline/custom/NativePipelineFwd.h | 13 ++- .../pipeline/custom/NativePipelineTypes.cpp | 17 +++- .../pipeline/custom/NativePipelineTypes.h | 88 ++++++++++++++++--- .../pipeline/custom/NativeSceneCulling.cpp | 44 ++++++---- 5 files changed, 134 insertions(+), 48 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 9ebb7d14c6a..8025ba2f8f9 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -30,12 +30,12 @@ #include "LayoutGraphUtils.h" #include "NativePipelineFwd.h" #include "NativePipelineTypes.h" +#include "NativeRenderGraphUtils.h" #include "NativeUtils.h" #include "PrivateTypes.h" #include "RenderGraphGraphs.h" #include "RenderGraphTypes.h" #include "RenderingModule.h" -#include "NativeRenderGraphUtils.h" #include "cocos/renderer/gfx-base/GFXBarrier.h" #include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/gfx-base/GFXDescriptorSetLayout.h" @@ -64,7 +64,7 @@ constexpr gfx::Color RASTER_UPLOAD_COLOR{1.0, 1.0, 0.0, 1.0}; constexpr gfx::Color RENDER_QUEUE_COLOR{0.0, 0.5, 0.5, 1.0}; constexpr gfx::Color COMPUTE_COLOR{0.0, 0.0, 1.0, 1.0}; -gfx::MarkerInfo makeMarkerInfo(const char *str, const gfx::Color &color) { +gfx::MarkerInfo makeMarkerInfo(const char* str, const gfx::Color& color) { return gfx::MarkerInfo{str, color}; } @@ -1180,7 +1180,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { if (subpass.subpassID) { ctx.cmdBuff->nextSubpass(); } - //ctx.cmdBuff->setViewport(subpass); + // ctx.cmdBuff->setViewport(subpass); tryBindPerPassDescriptorSet(vertID); ctx.subpassIndex = subpass.subpassID; // noop @@ -1381,16 +1381,16 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } const auto* scene = camera->getScene(); const auto& queueDesc = ctx.context.sceneCulling.sceneQueryIndex.at(sceneID); - const auto& queue = ctx.context.sceneCulling.renderQueues[queueDesc.renderQueueTarget]; + const auto& queue = ctx.context.sceneCulling.renderQueues[queueDesc.renderQueueTarget.value]; queue.opaqueQueue.recordCommandBuffer( ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); queue.opaqueInstancingQueue.recordCommandBuffer( ctx.currentPass, ctx.cmdBuff); queue.transparentQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); + ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); queue.transparentInstancingQueue.recordCommandBuffer( ctx.currentPass, ctx.cmdBuff); - if(any(sceneData.flags & SceneFlags::REFLECTION_PROBE)) { + if (any(sceneData.flags & SceneFlags::REFLECTION_PROBE)) { queue.probeQueue.removeMacro(); } if (any(sceneData.flags & SceneFlags::UI)) { @@ -1674,7 +1674,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { vertID, ctx.g, [&](const RasterPass& pass) { #if CC_DEBUG - ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RASTER_COLOR)); + ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RASTER_COLOR)); #endif mountResources(pass); { @@ -1685,13 +1685,13 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { // update UniformBuffers and DescriptorSets in all children { #if CC_DEBUG - ctx.cmdBuff->beginMarker(makeMarkerInfo("Upload", RASTER_UPLOAD_COLOR)); + ctx.cmdBuff->beginMarker(makeMarkerInfo("Upload", RASTER_UPLOAD_COLOR)); #endif auto colors = ctx.g.colors(ctx.scratch); RenderGraphUploadVisitor visitor{{}, ctx}; boost::depth_first_visit(gv, vertID, visitor, get(colors, ctx.g)); #if CC_DEBUG - ctx.cmdBuff->endMarker(); + ctx.cmdBuff->endMarker(); #endif } if (pass.showStatistics) { @@ -1799,7 +1799,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { end(pass, vertID); rearBarriers(vertID); #if CC_DEBUG - ctx.cmdBuff->endMarker(); + ctx.cmdBuff->endMarker(); #endif }, [&](const RasterSubpass& subpass) { diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 903eeb19a50..f29a0004ff6 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -75,11 +75,13 @@ struct QuadResource; enum class ResourceType; struct SceneResource; - -using CullingTarget = ccstd::variant; - struct CullingKey; +struct FrustumCullingID; struct CullingQueries; +struct LightBoundsCullingID; +struct LightBoundsCullingKey; +struct LightBoundsCullingQueries; +struct DrawQueueID; struct NativeRenderQueueDesc; struct SceneCulling; struct NativeRenderContext; @@ -100,6 +102,11 @@ struct hash { hash_t operator()(const cc::render::CullingKey& val) const noexcept; }; +template <> +struct hash { + hash_t operator()(const cc::render::LightBoundsCullingKey& val) const noexcept; +}; + } // namespace ccstd // clang-format on diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index fdebe1a6c40..913c6c8409f 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -180,15 +180,28 @@ CullingQueries::CullingQueries(CullingQueries&& rhs, const allocator_type& alloc CullingQueries::CullingQueries(CullingQueries const& rhs, const allocator_type& alloc) : culledResultIndex(rhs.culledResultIndex, alloc) {} +LightBoundsCullingQueries::LightBoundsCullingQueries(const allocator_type& alloc) noexcept +: lightCulledResultIndex(alloc) {} + +LightBoundsCullingQueries::LightBoundsCullingQueries(LightBoundsCullingQueries&& rhs, const allocator_type& alloc) +: lightCulledResultIndex(std::move(rhs.lightCulledResultIndex), alloc) {} + +LightBoundsCullingQueries::LightBoundsCullingQueries(LightBoundsCullingQueries const& rhs, const allocator_type& alloc) +: lightCulledResultIndex(rhs.lightCulledResultIndex, alloc) {} + SceneCulling::SceneCulling(const allocator_type& alloc) noexcept : sceneQueries(alloc), - culledResults(alloc), + frustumCulledResults(alloc), + lightCulledQueries(alloc), + lightCulledResults(alloc), renderQueues(alloc), sceneQueryIndex(alloc) {} SceneCulling::SceneCulling(SceneCulling&& rhs, const allocator_type& alloc) : sceneQueries(std::move(rhs.sceneQueries), alloc), - culledResults(std::move(rhs.culledResults), alloc), + frustumCulledResults(std::move(rhs.frustumCulledResults), alloc), + lightCulledQueries(std::move(rhs.lightCulledQueries), alloc), + lightCulledResults(std::move(rhs.lightCulledResults), alloc), renderQueues(std::move(rhs.renderQueues), alloc), sceneQueryIndex(std::move(rhs.sceneQueryIndex), alloc), numCullingQueries(rhs.numCullingQueries), diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index b843ae7314c..47b2119d97e 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1178,8 +1178,6 @@ struct SceneResource { ccstd::pmr::unordered_map> storageImages; }; -using CullingTarget = ccstd::variant; - struct CullingKey { const scene::Camera* camera{nullptr}; const scene::ReflectionProbe* probe{nullptr}; @@ -1197,6 +1195,14 @@ inline bool operator!=(const CullingKey& lhs, const CullingKey& rhs) noexcept { return !(lhs == rhs); } +struct FrustumCullingID { + explicit operator uint32_t() const { + return value; + } + + uint32_t value{0xFFFFFFFF}; +}; + struct CullingQueries { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT @@ -1212,18 +1218,62 @@ struct CullingQueries { CullingQueries& operator=(CullingQueries&& rhs) = default; CullingQueries& operator=(CullingQueries const& rhs) = default; - ccstd::pmr::unordered_map culledResultIndex; + ccstd::pmr::unordered_map culledResultIndex; +}; + +struct LightBoundsCullingID { + explicit operator uint32_t() const { + return value; + } + + uint32_t value{0xFFFFFFFF}; +}; + +struct LightBoundsCullingKey { + const scene::Camera* cameraTarget{nullptr}; + const scene::ReflectionProbe* probeTarget{nullptr}; + const scene::Light* cullingLight{nullptr}; +}; + +inline bool operator==(const LightBoundsCullingKey& lhs, const LightBoundsCullingKey& rhs) noexcept { + return std::forward_as_tuple(lhs.cameraTarget, lhs.probeTarget, lhs.cullingLight) == + std::forward_as_tuple(rhs.cameraTarget, rhs.probeTarget, rhs.cullingLight); +} + +inline bool operator!=(const LightBoundsCullingKey& lhs, const LightBoundsCullingKey& rhs) noexcept { + return !(lhs == rhs); +} + +struct LightBoundsCullingQueries { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {lightCulledResultIndex.get_allocator().resource()}; + } + + LightBoundsCullingQueries(const allocator_type& alloc) noexcept; // NOLINT + LightBoundsCullingQueries(LightBoundsCullingQueries&& rhs, const allocator_type& alloc); + LightBoundsCullingQueries(LightBoundsCullingQueries const& rhs, const allocator_type& alloc); + + LightBoundsCullingQueries(LightBoundsCullingQueries&& rhs) noexcept = default; + LightBoundsCullingQueries(LightBoundsCullingQueries const& rhs) = delete; + LightBoundsCullingQueries& operator=(LightBoundsCullingQueries&& rhs) = default; + LightBoundsCullingQueries& operator=(LightBoundsCullingQueries const& rhs) = default; + + ccstd::pmr::unordered_map lightCulledResultIndex; +}; + +struct DrawQueueID { + explicit operator uint32_t() const { + return value; + } + + uint32_t value{0xFFFFFFFF}; }; struct NativeRenderQueueDesc { - NativeRenderQueueDesc() = default; - NativeRenderQueueDesc(uint32_t culledSourceIn, uint32_t renderQueueTargetIn, scene::LightType lightTypeIn) noexcept // NOLINT - : culledSource(culledSourceIn), - renderQueueTarget(renderQueueTargetIn), - lightType(lightTypeIn) {} - - uint32_t culledSource{0xFFFFFFFF}; - uint32_t renderQueueTarget{0xFFFFFFFF}; + FrustumCullingID frustumCulledResultID; + LightBoundsCullingID lightBoundsCulledResultID; + DrawQueueID renderQueueTarget; scene::LightType lightType{scene::LightType::UNKNOWN}; }; @@ -1244,14 +1294,16 @@ struct SceneCulling { void clear() noexcept; void buildRenderQueues(const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData); private: - uint32_t getOrCreateSceneCullingQuery(const SceneData& sceneData); - uint32_t createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); + FrustumCullingID getOrCreateSceneCullingQuery(const SceneData& sceneData); + DrawQueueID createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); void collectCullingQueries(const RenderGraph& rg, const LayoutGraphData& lg); void batchCulling(const pipeline::PipelineSceneData& pplSceneData); void fillRenderQueues(const RenderGraph& rg, const pipeline::PipelineSceneData& pplSceneData); public: ccstd::pmr::unordered_map sceneQueries; - ccstd::pmr::vector> culledResults; + ccstd::pmr::vector> frustumCulledResults; + ccstd::pmr::unordered_map lightCulledQueries; + ccstd::pmr::vector> lightCulledResults; ccstd::pmr::vector renderQueues; PmrFlatMap sceneQueryIndex; uint32_t numCullingQueries{0}; @@ -1509,6 +1561,14 @@ inline hash_t hash::operator()(const cc::render::Culling return seed; } +inline hash_t hash::operator()(const cc::render::LightBoundsCullingKey& val) const noexcept { + hash_t seed = 0; + hash_combine(seed, val.cameraTarget); + hash_combine(seed, val.probeTarget); + hash_combine(seed, val.cullingLight); + return seed; +} + } // namespace ccstd // clang-format on diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 70613e6b1d7..2bceac9bfb0 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -30,7 +30,7 @@ bool NativeRenderQueue::empty() const noexcept { transparentInstancingQueue.empty(); } -uint32_t SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sceneData) { +FrustumCullingID SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sceneData) { const auto* const scene = sceneData.scene; // get or add scene to queries auto& queries = sceneQueries[scene]; @@ -53,21 +53,21 @@ uint32_t SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sceneData) if (iter == queries.culledResultIndex.end()) { // create query source // make query source id - const auto sourceID = numCullingQueries++; - if (numCullingQueries > culledResults.size()) { + const FrustumCullingID frustomCulledResultID{numCullingQueries++}; + if (numCullingQueries > frustumCulledResults.size()) { // space is not enough, create query source - CC_EXPECTS(numCullingQueries == culledResults.size() + 1); - culledResults.emplace_back(); + CC_EXPECTS(numCullingQueries == frustumCulledResults.size() + 1); + frustumCulledResults.emplace_back(); } // add query source to query index bool added = false; - std::tie(iter, added) = queries.culledResultIndex.emplace(key, sourceID); + std::tie(iter, added) = queries.culledResultIndex.emplace(key, frustomCulledResultID); CC_ENSURES(added); } return iter->second; } -uint32_t SceneCulling::createRenderQueue( +DrawQueueID SceneCulling::createRenderQueue( SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID) { const auto targetID = numRenderQueues++; if (numRenderQueues > renderQueues.size()) { @@ -81,7 +81,7 @@ uint32_t SceneCulling::createRenderQueue( CC_EXPECTS(rq.subpassOrPassLayoutID == 0xFFFFFFFF); rq.sceneFlags = sceneFlags; rq.subpassOrPassLayoutID = subpassOrPassLayoutID; - return targetID; + return DrawQueueID{targetID}; } void SceneCulling::collectCullingQueries( @@ -95,7 +95,7 @@ void SceneCulling::collectCullingQueries( CC_EXPECTS(false); continue; } - const auto sourceID = getOrCreateSceneCullingQuery(sceneData); + const auto frustomCulledResultID = getOrCreateSceneCullingQuery(sceneData); const auto layoutID = getSubpassOrPassID(vertID, rg, lg); const auto targetID = createRenderQueue(sceneData.flags, layoutID); const auto lightType = sceneData.light.light @@ -103,7 +103,13 @@ void SceneCulling::collectCullingQueries( : scene::LightType::UNKNOWN; // add render queue to query source - sceneQueryIndex.emplace(vertID, NativeRenderQueueDesc(sourceID, targetID, lightType)); + sceneQueryIndex.emplace( + vertID, + NativeRenderQueueDesc{ + frustomCulledResultID, + LightBoundsCullingID{}, + targetID, + lightType}); } } @@ -246,7 +252,7 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) for (const auto& [scene, queries] : sceneQueries) { CC_ENSURES(scene); - for (const auto& [key, sourceID] : queries.culledResultIndex) { + for (const auto& [key, frustomCulledResultID] : queries.culledResultIndex) { CC_EXPECTS(key.camera); CC_EXPECTS(key.camera->getScene() == scene); const auto* light = key.light; @@ -254,8 +260,8 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) const auto bCastShadow = key.castShadow; const auto* probe = key.probe; const auto& camera = probe ? *probe->getCamera() : *key.camera; - CC_EXPECTS(sourceID < culledResults.size()); - auto& models = culledResults[sourceID]; + CC_EXPECTS(frustomCulledResultID.value < frustumCulledResults.size()); + auto& models = frustumCulledResults[frustomCulledResultID.value]; if (probe) { sceneCulling( @@ -414,7 +420,7 @@ void SceneCulling::fillRenderQueues( const auto* const skybox = pplSceneData.getSkybox(); for (auto&& [sceneID, desc] : sceneQueryIndex) { CC_EXPECTS(holds(sceneID, rg)); - const auto sourceID = desc.culledSource; + const auto frustomCulledResultID = desc.frustumCulledResultID; const auto targetID = desc.renderQueueTarget; const auto& sceneData = get(SceneTag{}, sceneID, rg); @@ -436,12 +442,12 @@ void SceneCulling::fillRenderQueues( CC_EXPECTS(phaseLayoutID != LayoutGraphData::null_vertex()); // culling source - CC_EXPECTS(sourceID < culledResults.size()); - const auto& sourceModels = culledResults[sourceID]; + CC_EXPECTS(frustomCulledResultID.value < frustumCulledResults.size()); + const auto& sourceModels = frustumCulledResults[frustomCulledResultID.value]; // native queue target - CC_EXPECTS(targetID < renderQueues.size()); - auto& nativeQueue = renderQueues[targetID]; + CC_EXPECTS(targetID.value < renderQueues.size()); + auto& nativeQueue = renderQueues[targetID.value]; CC_EXPECTS(nativeQueue.empty()); // skybox @@ -472,7 +478,7 @@ void SceneCulling::buildRenderQueues( void SceneCulling::clear() noexcept { sceneQueries.clear(); - for (auto& c : culledResults) { + for (auto& c : frustumCulledResults) { c.clear(); } for (auto& q : renderQueues) { From 4cb1940d74ec974a079e467c05810136886ccadc Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 7 Sep 2023 16:44:22 +0800 Subject: [PATCH 52/82] enhance safety --- .../pipeline/custom/NativePipelineFwd.h | 10 +++--- .../pipeline/custom/NativePipelineTypes.cpp | 6 ++-- .../pipeline/custom/NativePipelineTypes.h | 36 +++++++++---------- .../pipeline/custom/NativeSceneCulling.cpp | 13 +++---- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index f29a0004ff6..15f6c51f051 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -75,13 +75,13 @@ struct QuadResource; enum class ResourceType; struct SceneResource; -struct CullingKey; +struct FrustumCullingKey; struct FrustumCullingID; -struct CullingQueries; +struct FrustumCullingQueries; struct LightBoundsCullingID; struct LightBoundsCullingKey; struct LightBoundsCullingQueries; -struct DrawQueueID; +struct NativeRenderQueueID; struct NativeRenderQueueDesc; struct SceneCulling; struct NativeRenderContext; @@ -98,8 +98,8 @@ class NativeRenderingModule; namespace ccstd { template <> -struct hash { - hash_t operator()(const cc::render::CullingKey& val) const noexcept; +struct hash { + hash_t operator()(const cc::render::FrustumCullingKey& val) const noexcept; }; template <> diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 913c6c8409f..3bdbfa7dc31 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -171,13 +171,13 @@ SceneResource::SceneResource(SceneResource&& rhs, const allocator_type& alloc) storageBuffers(std::move(rhs.storageBuffers), alloc), storageImages(std::move(rhs.storageImages), alloc) {} -CullingQueries::CullingQueries(const allocator_type& alloc) noexcept +FrustumCullingQueries::FrustumCullingQueries(const allocator_type& alloc) noexcept : culledResultIndex(alloc) {} -CullingQueries::CullingQueries(CullingQueries&& rhs, const allocator_type& alloc) +FrustumCullingQueries::FrustumCullingQueries(FrustumCullingQueries&& rhs, const allocator_type& alloc) : culledResultIndex(std::move(rhs.culledResultIndex), alloc) {} -CullingQueries::CullingQueries(CullingQueries const& rhs, const allocator_type& alloc) +FrustumCullingQueries::FrustumCullingQueries(FrustumCullingQueries const& rhs, const allocator_type& alloc) : culledResultIndex(rhs.culledResultIndex, alloc) {} LightBoundsCullingQueries::LightBoundsCullingQueries(const allocator_type& alloc) noexcept diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 47b2119d97e..e1518795201 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1178,7 +1178,7 @@ struct SceneResource { ccstd::pmr::unordered_map> storageImages; }; -struct CullingKey { +struct FrustumCullingKey { const scene::Camera* camera{nullptr}; const scene::ReflectionProbe* probe{nullptr}; const scene::Light* light{nullptr}; @@ -1186,12 +1186,12 @@ struct CullingKey { bool castShadow{false}; }; -inline bool operator==(const CullingKey& lhs, const CullingKey& rhs) noexcept { +inline bool operator==(const FrustumCullingKey& lhs, const FrustumCullingKey& rhs) noexcept { return std::forward_as_tuple(lhs.camera, lhs.probe, lhs.light, lhs.lightLevel, lhs.castShadow) == std::forward_as_tuple(rhs.camera, rhs.probe, rhs.light, rhs.lightLevel, rhs.castShadow); } -inline bool operator!=(const CullingKey& lhs, const CullingKey& rhs) noexcept { +inline bool operator!=(const FrustumCullingKey& lhs, const FrustumCullingKey& rhs) noexcept { return !(lhs == rhs); } @@ -1203,22 +1203,22 @@ struct FrustumCullingID { uint32_t value{0xFFFFFFFF}; }; -struct CullingQueries { +struct FrustumCullingQueries { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT return {culledResultIndex.get_allocator().resource()}; } - CullingQueries(const allocator_type& alloc) noexcept; // NOLINT - CullingQueries(CullingQueries&& rhs, const allocator_type& alloc); - CullingQueries(CullingQueries const& rhs, const allocator_type& alloc); + FrustumCullingQueries(const allocator_type& alloc) noexcept; // NOLINT + FrustumCullingQueries(FrustumCullingQueries&& rhs, const allocator_type& alloc); + FrustumCullingQueries(FrustumCullingQueries const& rhs, const allocator_type& alloc); - CullingQueries(CullingQueries&& rhs) noexcept = default; - CullingQueries(CullingQueries const& rhs) = delete; - CullingQueries& operator=(CullingQueries&& rhs) = default; - CullingQueries& operator=(CullingQueries const& rhs) = default; + FrustumCullingQueries(FrustumCullingQueries&& rhs) noexcept = default; + FrustumCullingQueries(FrustumCullingQueries const& rhs) = delete; + FrustumCullingQueries& operator=(FrustumCullingQueries&& rhs) = default; + FrustumCullingQueries& operator=(FrustumCullingQueries const& rhs) = default; - ccstd::pmr::unordered_map culledResultIndex; + ccstd::pmr::unordered_map culledResultIndex; }; struct LightBoundsCullingID { @@ -1262,7 +1262,7 @@ struct LightBoundsCullingQueries { ccstd::pmr::unordered_map lightCulledResultIndex; }; -struct DrawQueueID { +struct NativeRenderQueueID { explicit operator uint32_t() const { return value; } @@ -1273,7 +1273,7 @@ struct DrawQueueID { struct NativeRenderQueueDesc { FrustumCullingID frustumCulledResultID; LightBoundsCullingID lightBoundsCulledResultID; - DrawQueueID renderQueueTarget; + NativeRenderQueueID renderQueueTarget; scene::LightType lightType{scene::LightType::UNKNOWN}; }; @@ -1294,13 +1294,13 @@ struct SceneCulling { void clear() noexcept; void buildRenderQueues(const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData); private: - FrustumCullingID getOrCreateSceneCullingQuery(const SceneData& sceneData); - DrawQueueID createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); + FrustumCullingID getOrCreateFrustumCulling(const SceneData& sceneData); + NativeRenderQueueID createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); void collectCullingQueries(const RenderGraph& rg, const LayoutGraphData& lg); void batchCulling(const pipeline::PipelineSceneData& pplSceneData); void fillRenderQueues(const RenderGraph& rg, const pipeline::PipelineSceneData& pplSceneData); public: - ccstd::pmr::unordered_map sceneQueries; + ccstd::pmr::unordered_map sceneQueries; ccstd::pmr::vector> frustumCulledResults; ccstd::pmr::unordered_map lightCulledQueries; ccstd::pmr::vector> lightCulledResults; @@ -1551,7 +1551,7 @@ class NativeRenderingModule final : public RenderingModule { namespace ccstd { -inline hash_t hash::operator()(const cc::render::CullingKey& val) const noexcept { +inline hash_t hash::operator()(const cc::render::FrustumCullingKey& val) const noexcept { hash_t seed = 0; hash_combine(seed, val.camera); hash_combine(seed, val.probe); diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 2bceac9bfb0..6bb0f4dec64 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -30,7 +30,7 @@ bool NativeRenderQueue::empty() const noexcept { transparentInstancingQueue.empty(); } -FrustumCullingID SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sceneData) { +FrustumCullingID SceneCulling::getOrCreateFrustumCulling(const SceneData& sceneData) { const auto* const scene = sceneData.scene; // get or add scene to queries auto& queries = sceneQueries[scene]; @@ -40,7 +40,7 @@ FrustumCullingID SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sce // get or create query source // make query key - const auto key = CullingKey{ + const auto key = FrustumCullingKey{ sceneData.camera, sceneData.light.probe, sceneData.light.light, @@ -67,7 +67,7 @@ FrustumCullingID SceneCulling::getOrCreateSceneCullingQuery(const SceneData& sce return iter->second; } -DrawQueueID SceneCulling::createRenderQueue( +NativeRenderQueueID SceneCulling::createRenderQueue( SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID) { const auto targetID = numRenderQueues++; if (numRenderQueues > renderQueues.size()) { @@ -81,7 +81,7 @@ DrawQueueID SceneCulling::createRenderQueue( CC_EXPECTS(rq.subpassOrPassLayoutID == 0xFFFFFFFF); rq.sceneFlags = sceneFlags; rq.subpassOrPassLayoutID = subpassOrPassLayoutID; - return DrawQueueID{targetID}; + return NativeRenderQueueID{targetID}; } void SceneCulling::collectCullingQueries( @@ -95,7 +95,7 @@ void SceneCulling::collectCullingQueries( CC_EXPECTS(false); continue; } - const auto frustomCulledResultID = getOrCreateSceneCullingQuery(sceneData); + const auto frustomCulledResultID = getOrCreateFrustumCulling(sceneData); const auto layoutID = getSubpassOrPassID(vertID, rg, lg); const auto targetID = createRenderQueue(sceneData.flags, layoutID); const auto lightType = sceneData.light.light @@ -109,7 +109,8 @@ void SceneCulling::collectCullingQueries( frustomCulledResultID, LightBoundsCullingID{}, targetID, - lightType}); + lightType, + }); } } From 8ededf492dba7188dc2fe52b847694f7eb446b87 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 7 Sep 2023 17:10:55 +0800 Subject: [PATCH 53/82] adding light bounds culling --- .../pipeline/custom/NativePipelineFwd.h | 9 ++- .../pipeline/custom/NativePipelineTypes.cpp | 37 ++++----- .../pipeline/custom/NativePipelineTypes.h | 79 ++++++++++++------- .../pipeline/custom/NativeSceneCulling.cpp | 78 +++++++++++++++--- 4 files changed, 140 insertions(+), 63 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 15f6c51f051..dc124395c27 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -77,10 +77,10 @@ enum class ResourceType; struct SceneResource; struct FrustumCullingKey; struct FrustumCullingID; -struct FrustumCullingQueries; +struct FrustumCulling; struct LightBoundsCullingID; struct LightBoundsCullingKey; -struct LightBoundsCullingQueries; +struct LightBoundsCulling; struct NativeRenderQueueID; struct NativeRenderQueueDesc; struct SceneCulling; @@ -102,6 +102,11 @@ struct hash { hash_t operator()(const cc::render::FrustumCullingKey& val) const noexcept; }; +template <> +struct hash { + hash_t operator()(const cc::render::FrustumCullingID& val) const noexcept; +}; + template <> struct hash { hash_t operator()(const cc::render::LightBoundsCullingKey& val) const noexcept; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 3bdbfa7dc31..7809c2f42c8 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -171,40 +171,41 @@ SceneResource::SceneResource(SceneResource&& rhs, const allocator_type& alloc) storageBuffers(std::move(rhs.storageBuffers), alloc), storageImages(std::move(rhs.storageImages), alloc) {} -FrustumCullingQueries::FrustumCullingQueries(const allocator_type& alloc) noexcept +FrustumCulling::FrustumCulling(const allocator_type& alloc) noexcept : culledResultIndex(alloc) {} -FrustumCullingQueries::FrustumCullingQueries(FrustumCullingQueries&& rhs, const allocator_type& alloc) +FrustumCulling::FrustumCulling(FrustumCulling&& rhs, const allocator_type& alloc) : culledResultIndex(std::move(rhs.culledResultIndex), alloc) {} -FrustumCullingQueries::FrustumCullingQueries(FrustumCullingQueries const& rhs, const allocator_type& alloc) +FrustumCulling::FrustumCulling(FrustumCulling const& rhs, const allocator_type& alloc) : culledResultIndex(rhs.culledResultIndex, alloc) {} -LightBoundsCullingQueries::LightBoundsCullingQueries(const allocator_type& alloc) noexcept -: lightCulledResultIndex(alloc) {} +LightBoundsCulling::LightBoundsCulling(const allocator_type& alloc) noexcept +: resultIndex(alloc) {} -LightBoundsCullingQueries::LightBoundsCullingQueries(LightBoundsCullingQueries&& rhs, const allocator_type& alloc) -: lightCulledResultIndex(std::move(rhs.lightCulledResultIndex), alloc) {} +LightBoundsCulling::LightBoundsCulling(LightBoundsCulling&& rhs, const allocator_type& alloc) +: resultIndex(std::move(rhs.resultIndex), alloc) {} -LightBoundsCullingQueries::LightBoundsCullingQueries(LightBoundsCullingQueries const& rhs, const allocator_type& alloc) -: lightCulledResultIndex(rhs.lightCulledResultIndex, alloc) {} +LightBoundsCulling::LightBoundsCulling(LightBoundsCulling const& rhs, const allocator_type& alloc) +: resultIndex(rhs.resultIndex, alloc) {} SceneCulling::SceneCulling(const allocator_type& alloc) noexcept -: sceneQueries(alloc), - frustumCulledResults(alloc), - lightCulledQueries(alloc), - lightCulledResults(alloc), +: frustumCullings(alloc), + frustumCullingResults(alloc), + lightBoundsCullings(alloc), + lightBoundsCullingResults(alloc), renderQueues(alloc), sceneQueryIndex(alloc) {} SceneCulling::SceneCulling(SceneCulling&& rhs, const allocator_type& alloc) -: sceneQueries(std::move(rhs.sceneQueries), alloc), - frustumCulledResults(std::move(rhs.frustumCulledResults), alloc), - lightCulledQueries(std::move(rhs.lightCulledQueries), alloc), - lightCulledResults(std::move(rhs.lightCulledResults), alloc), +: frustumCullings(std::move(rhs.frustumCullings), alloc), + frustumCullingResults(std::move(rhs.frustumCullingResults), alloc), + lightBoundsCullings(std::move(rhs.lightBoundsCullings), alloc), + lightBoundsCullingResults(std::move(rhs.lightBoundsCullingResults), alloc), renderQueues(std::move(rhs.renderQueues), alloc), sceneQueryIndex(std::move(rhs.sceneQueryIndex), alloc), - numCullingQueries(rhs.numCullingQueries), + numFrustumCulling(rhs.numFrustumCulling), + numLightBoundsCulling(rhs.numLightBoundsCulling), numRenderQueues(rhs.numRenderQueues), gpuCullingPassID(rhs.gpuCullingPassID) {} diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index e1518795201..c3a67b938fa 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1203,20 +1203,29 @@ struct FrustumCullingID { uint32_t value{0xFFFFFFFF}; }; -struct FrustumCullingQueries { +inline bool operator==(const FrustumCullingID& lhs, const FrustumCullingID& rhs) noexcept { + return std::forward_as_tuple(lhs.value) == + std::forward_as_tuple(rhs.value); +} + +inline bool operator!=(const FrustumCullingID& lhs, const FrustumCullingID& rhs) noexcept { + return !(lhs == rhs); +} + +struct FrustumCulling { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT return {culledResultIndex.get_allocator().resource()}; } - FrustumCullingQueries(const allocator_type& alloc) noexcept; // NOLINT - FrustumCullingQueries(FrustumCullingQueries&& rhs, const allocator_type& alloc); - FrustumCullingQueries(FrustumCullingQueries const& rhs, const allocator_type& alloc); + FrustumCulling(const allocator_type& alloc) noexcept; // NOLINT + FrustumCulling(FrustumCulling&& rhs, const allocator_type& alloc); + FrustumCulling(FrustumCulling const& rhs, const allocator_type& alloc); - FrustumCullingQueries(FrustumCullingQueries&& rhs) noexcept = default; - FrustumCullingQueries(FrustumCullingQueries const& rhs) = delete; - FrustumCullingQueries& operator=(FrustumCullingQueries&& rhs) = default; - FrustumCullingQueries& operator=(FrustumCullingQueries const& rhs) = default; + FrustumCulling(FrustumCulling&& rhs) noexcept = default; + FrustumCulling(FrustumCulling const& rhs) = delete; + FrustumCulling& operator=(FrustumCulling&& rhs) = default; + FrustumCulling& operator=(FrustumCulling const& rhs) = default; ccstd::pmr::unordered_map culledResultIndex; }; @@ -1230,36 +1239,37 @@ struct LightBoundsCullingID { }; struct LightBoundsCullingKey { - const scene::Camera* cameraTarget{nullptr}; - const scene::ReflectionProbe* probeTarget{nullptr}; + FrustumCullingID frustumCullingID; + const scene::Camera* camera{nullptr}; + const scene::ReflectionProbe* probe{nullptr}; const scene::Light* cullingLight{nullptr}; }; inline bool operator==(const LightBoundsCullingKey& lhs, const LightBoundsCullingKey& rhs) noexcept { - return std::forward_as_tuple(lhs.cameraTarget, lhs.probeTarget, lhs.cullingLight) == - std::forward_as_tuple(rhs.cameraTarget, rhs.probeTarget, rhs.cullingLight); + return std::forward_as_tuple(lhs.frustumCullingID, lhs.camera, lhs.probe, lhs.cullingLight) == + std::forward_as_tuple(rhs.frustumCullingID, rhs.camera, rhs.probe, rhs.cullingLight); } inline bool operator!=(const LightBoundsCullingKey& lhs, const LightBoundsCullingKey& rhs) noexcept { return !(lhs == rhs); } -struct LightBoundsCullingQueries { +struct LightBoundsCulling { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT - return {lightCulledResultIndex.get_allocator().resource()}; + return {resultIndex.get_allocator().resource()}; } - LightBoundsCullingQueries(const allocator_type& alloc) noexcept; // NOLINT - LightBoundsCullingQueries(LightBoundsCullingQueries&& rhs, const allocator_type& alloc); - LightBoundsCullingQueries(LightBoundsCullingQueries const& rhs, const allocator_type& alloc); + LightBoundsCulling(const allocator_type& alloc) noexcept; // NOLINT + LightBoundsCulling(LightBoundsCulling&& rhs, const allocator_type& alloc); + LightBoundsCulling(LightBoundsCulling const& rhs, const allocator_type& alloc); - LightBoundsCullingQueries(LightBoundsCullingQueries&& rhs) noexcept = default; - LightBoundsCullingQueries(LightBoundsCullingQueries const& rhs) = delete; - LightBoundsCullingQueries& operator=(LightBoundsCullingQueries&& rhs) = default; - LightBoundsCullingQueries& operator=(LightBoundsCullingQueries const& rhs) = default; + LightBoundsCulling(LightBoundsCulling&& rhs) noexcept = default; + LightBoundsCulling(LightBoundsCulling const& rhs) = delete; + LightBoundsCulling& operator=(LightBoundsCulling&& rhs) = default; + LightBoundsCulling& operator=(LightBoundsCulling const& rhs) = default; - ccstd::pmr::unordered_map lightCulledResultIndex; + ccstd::pmr::unordered_map resultIndex; }; struct NativeRenderQueueID { @@ -1280,7 +1290,7 @@ struct NativeRenderQueueDesc { struct SceneCulling { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT - return {sceneQueries.get_allocator().resource()}; + return {frustumCullings.get_allocator().resource()}; } SceneCulling(const allocator_type& alloc) noexcept; // NOLINT @@ -1295,18 +1305,20 @@ struct SceneCulling { void buildRenderQueues(const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData); private: FrustumCullingID getOrCreateFrustumCulling(const SceneData& sceneData); + LightBoundsCullingID getOrCreateLightBoundsCulling(const SceneData& sceneData, FrustumCullingID frustumCullingID); NativeRenderQueueID createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); void collectCullingQueries(const RenderGraph& rg, const LayoutGraphData& lg); void batchCulling(const pipeline::PipelineSceneData& pplSceneData); void fillRenderQueues(const RenderGraph& rg, const pipeline::PipelineSceneData& pplSceneData); public: - ccstd::pmr::unordered_map sceneQueries; - ccstd::pmr::vector> frustumCulledResults; - ccstd::pmr::unordered_map lightCulledQueries; - ccstd::pmr::vector> lightCulledResults; + ccstd::pmr::unordered_map frustumCullings; + ccstd::pmr::vector> frustumCullingResults; + ccstd::pmr::unordered_map lightBoundsCullings; + ccstd::pmr::vector> lightBoundsCullingResults; ccstd::pmr::vector renderQueues; PmrFlatMap sceneQueryIndex; - uint32_t numCullingQueries{0}; + uint32_t numFrustumCulling{0}; + uint32_t numLightBoundsCulling{0}; uint32_t numRenderQueues{0}; uint32_t gpuCullingPassID{0xFFFFFFFF}; }; @@ -1561,10 +1573,17 @@ inline hash_t hash::operator()(const cc::render:: return seed; } +inline hash_t hash::operator()(const cc::render::FrustumCullingID& val) const noexcept { + hash_t seed = 0; + hash_combine(seed, val.value); + return seed; +} + inline hash_t hash::operator()(const cc::render::LightBoundsCullingKey& val) const noexcept { hash_t seed = 0; - hash_combine(seed, val.cameraTarget); - hash_combine(seed, val.probeTarget); + hash_combine(seed, val.frustumCullingID); + hash_combine(seed, val.camera); + hash_combine(seed, val.probe); hash_combine(seed, val.cullingLight); return seed; } diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 6bb0f4dec64..943b094c741 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -33,7 +33,7 @@ bool NativeRenderQueue::empty() const noexcept { FrustumCullingID SceneCulling::getOrCreateFrustumCulling(const SceneData& sceneData) { const auto* const scene = sceneData.scene; // get or add scene to queries - auto& queries = sceneQueries[scene]; + auto& queries = frustumCullings[scene]; // check cast shadow const bool bCastShadow = any(sceneData.flags & SceneFlags::SHADOW_CASTER); @@ -53,11 +53,11 @@ FrustumCullingID SceneCulling::getOrCreateFrustumCulling(const SceneData& sceneD if (iter == queries.culledResultIndex.end()) { // create query source // make query source id - const FrustumCullingID frustomCulledResultID{numCullingQueries++}; - if (numCullingQueries > frustumCulledResults.size()) { + const FrustumCullingID frustomCulledResultID{numFrustumCulling++}; + if (numFrustumCulling > frustumCullingResults.size()) { // space is not enough, create query source - CC_EXPECTS(numCullingQueries == frustumCulledResults.size() + 1); - frustumCulledResults.emplace_back(); + CC_EXPECTS(numFrustumCulling == frustumCullingResults.size() + 1); + frustumCullingResults.emplace_back(); } // add query source to query index bool added = false; @@ -67,6 +67,46 @@ FrustumCullingID SceneCulling::getOrCreateFrustumCulling(const SceneData& sceneD return iter->second; } +LightBoundsCullingID SceneCulling::getOrCreateLightBoundsCulling( + const SceneData& sceneData, FrustumCullingID frustumCullingID) { + if (!any(sceneData.cullingFlags & CullingFlags::LIGHT_BOUNDS)) { + return {}; + } + + CC_EXPECTS(sceneData.light.light); + const auto* const scene = sceneData.scene; + CC_EXPECTS(scene); + + auto& queries = lightBoundsCullings[scene]; + + // get or create query source + // make query key + const auto key = LightBoundsCullingKey{ + frustumCullingID, + sceneData.camera, + sceneData.light.probe, + sceneData.light.light, + }; + + // find query source + auto iter = queries.resultIndex.find(key); + if (iter == queries.resultIndex.end()) { + // create query source + // make query source id + const LightBoundsCullingID lightBoundsCullingID{numLightBoundsCulling++}; + if (numLightBoundsCulling > lightBoundsCullingResults.size()) { + // space is not enough, create query source + CC_EXPECTS(numLightBoundsCulling == lightBoundsCullingResults.size() + 1); + lightBoundsCullingResults.emplace_back(); + } + // add query source to query index + bool added = false; + std::tie(iter, added) = queries.resultIndex.emplace(key, lightBoundsCullingID); + CC_ENSURES(added); + } + return iter->second; +} + NativeRenderQueueID SceneCulling::createRenderQueue( SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID) { const auto targetID = numRenderQueues++; @@ -251,7 +291,7 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) const auto* const skybox = pplSceneData.getSkybox(); const auto* const skyboxModel = skybox && skybox->isEnabled() ? skybox->getModel() : nullptr; - for (const auto& [scene, queries] : sceneQueries) { + for (const auto& [scene, queries] : frustumCullings) { CC_ENSURES(scene); for (const auto& [key, frustomCulledResultID] : queries.culledResultIndex) { CC_EXPECTS(key.camera); @@ -261,8 +301,8 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) const auto bCastShadow = key.castShadow; const auto* probe = key.probe; const auto& camera = probe ? *probe->getCamera() : *key.camera; - CC_EXPECTS(frustomCulledResultID.value < frustumCulledResults.size()); - auto& models = frustumCulledResults[frustomCulledResultID.value]; + CC_EXPECTS(frustomCulledResultID.value < frustumCullingResults.size()); + auto& models = frustumCullingResults[frustomCulledResultID.value]; if (probe) { sceneCulling( @@ -443,8 +483,8 @@ void SceneCulling::fillRenderQueues( CC_EXPECTS(phaseLayoutID != LayoutGraphData::null_vertex()); // culling source - CC_EXPECTS(frustomCulledResultID.value < frustumCulledResults.size()); - const auto& sourceModels = frustumCulledResults[frustomCulledResultID.value]; + CC_EXPECTS(frustomCulledResultID.value < frustumCullingResults.size()); + const auto& sourceModels = frustumCullingResults[frustomCulledResultID.value]; // native queue target CC_EXPECTS(targetID.value < renderQueues.size()); @@ -478,15 +518,27 @@ void SceneCulling::buildRenderQueues( } void SceneCulling::clear() noexcept { - sceneQueries.clear(); - for (auto& c : frustumCulledResults) { + // frustum culling + frustumCullings.clear(); + for (auto& c : frustumCullingResults) { c.clear(); } + // light bounds culling + lightBoundsCullings.clear(); + for (auto& c : lightBoundsCullingResults) { + c.clear(); + } + // native render queues for (auto& q : renderQueues) { q.clear(); } + + // clear render graph scene vertex query index sceneQueryIndex.clear(); - numCullingQueries = 0; + + // reset all counters + numFrustumCulling = 0; + numLightBoundsCulling = 0; numRenderQueues = 0; } From d6162a891b3ce3ae54aba4f8635cd67a0d60994e Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 7 Sep 2023 17:28:39 +0800 Subject: [PATCH 54/82] renderQueueIndex renamed --- .../cocos/renderer/pipeline/custom/NativeExecutor.cpp | 2 +- .../renderer/pipeline/custom/NativePipelineTypes.cpp | 4 ++-- .../renderer/pipeline/custom/NativePipelineTypes.h | 2 +- .../renderer/pipeline/custom/NativeSceneCulling.cpp | 10 ++++++---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 8025ba2f8f9..6d0a2b659a5 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -1380,7 +1380,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { tryBindPerPassDescriptorSet(sceneID); } const auto* scene = camera->getScene(); - const auto& queueDesc = ctx.context.sceneCulling.sceneQueryIndex.at(sceneID); + const auto& queueDesc = ctx.context.sceneCulling.renderQueueIndex.at(sceneID); const auto& queue = ctx.context.sceneCulling.renderQueues[queueDesc.renderQueueTarget.value]; queue.opaqueQueue.recordCommandBuffer( ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 7809c2f42c8..c53aa13684e 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -195,7 +195,7 @@ SceneCulling::SceneCulling(const allocator_type& alloc) noexcept lightBoundsCullings(alloc), lightBoundsCullingResults(alloc), renderQueues(alloc), - sceneQueryIndex(alloc) {} + renderQueueIndex(alloc) {} SceneCulling::SceneCulling(SceneCulling&& rhs, const allocator_type& alloc) : frustumCullings(std::move(rhs.frustumCullings), alloc), @@ -203,7 +203,7 @@ SceneCulling::SceneCulling(SceneCulling&& rhs, const allocator_type& alloc) lightBoundsCullings(std::move(rhs.lightBoundsCullings), alloc), lightBoundsCullingResults(std::move(rhs.lightBoundsCullingResults), alloc), renderQueues(std::move(rhs.renderQueues), alloc), - sceneQueryIndex(std::move(rhs.sceneQueryIndex), alloc), + renderQueueIndex(std::move(rhs.renderQueueIndex), alloc), numFrustumCulling(rhs.numFrustumCulling), numLightBoundsCulling(rhs.numLightBoundsCulling), numRenderQueues(rhs.numRenderQueues), diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index c3a67b938fa..b399c855654 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1316,7 +1316,7 @@ struct SceneCulling { ccstd::pmr::unordered_map lightBoundsCullings; ccstd::pmr::vector> lightBoundsCullingResults; ccstd::pmr::vector renderQueues; - PmrFlatMap sceneQueryIndex; + PmrFlatMap renderQueueIndex; uint32_t numFrustumCulling{0}; uint32_t numLightBoundsCulling{0}; uint32_t numRenderQueues{0}; diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 943b094c741..741e9b4f903 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -136,6 +136,7 @@ void SceneCulling::collectCullingQueries( continue; } const auto frustomCulledResultID = getOrCreateFrustumCulling(sceneData); + const auto lightBoundsCullingID = getOrCreateLightBoundsCulling(sceneData, frustomCulledResultID); const auto layoutID = getSubpassOrPassID(vertID, rg, lg); const auto targetID = createRenderQueue(sceneData.flags, layoutID); const auto lightType = sceneData.light.light @@ -143,11 +144,11 @@ void SceneCulling::collectCullingQueries( : scene::LightType::UNKNOWN; // add render queue to query source - sceneQueryIndex.emplace( + renderQueueIndex.emplace( vertID, NativeRenderQueueDesc{ frustomCulledResultID, - LightBoundsCullingID{}, + lightBoundsCullingID, targetID, lightType, }); @@ -459,7 +460,7 @@ void addRenderObject( void SceneCulling::fillRenderQueues( const RenderGraph& rg, const pipeline::PipelineSceneData& pplSceneData) { const auto* const skybox = pplSceneData.getSkybox(); - for (auto&& [sceneID, desc] : sceneQueryIndex) { + for (auto&& [sceneID, desc] : renderQueueIndex) { CC_EXPECTS(holds(sceneID, rg)); const auto frustomCulledResultID = desc.frustumCulledResultID; const auto targetID = desc.renderQueueTarget; @@ -534,7 +535,8 @@ void SceneCulling::clear() noexcept { } // clear render graph scene vertex query index - sceneQueryIndex.clear(); + renderQueueIndex.clear(); + // do not clear this->renderQueues, it is reused to avoid memory allocation // reset all counters numFrustumCulling = 0; From 5651057aa061a723fada8db5e3d36da5ad5d4d4a Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 8 Sep 2023 11:53:01 +0800 Subject: [PATCH 55/82] light bounds culling added --- .../pipeline/custom/NativePipelineTypes.cpp | 6 +- .../pipeline/custom/NativePipelineTypes.h | 7 +- .../pipeline/custom/NativeSceneCulling.cpp | 131 +++++++++++++++++- 3 files changed, 131 insertions(+), 13 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index c53aa13684e..1d4f2cdc285 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -172,13 +172,13 @@ SceneResource::SceneResource(SceneResource&& rhs, const allocator_type& alloc) storageImages(std::move(rhs.storageImages), alloc) {} FrustumCulling::FrustumCulling(const allocator_type& alloc) noexcept -: culledResultIndex(alloc) {} +: resultIndex(alloc) {} FrustumCulling::FrustumCulling(FrustumCulling&& rhs, const allocator_type& alloc) -: culledResultIndex(std::move(rhs.culledResultIndex), alloc) {} +: resultIndex(std::move(rhs.resultIndex), alloc) {} FrustumCulling::FrustumCulling(FrustumCulling const& rhs, const allocator_type& alloc) -: culledResultIndex(rhs.culledResultIndex, alloc) {} +: resultIndex(rhs.resultIndex, alloc) {} LightBoundsCulling::LightBoundsCulling(const allocator_type& alloc) noexcept : resultIndex(alloc) {} diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index b399c855654..46736baaaa5 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1215,7 +1215,7 @@ inline bool operator!=(const FrustumCullingID& lhs, const FrustumCullingID& rhs) struct FrustumCulling { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT - return {culledResultIndex.get_allocator().resource()}; + return {resultIndex.get_allocator().resource()}; } FrustumCulling(const allocator_type& alloc) noexcept; // NOLINT @@ -1227,7 +1227,7 @@ struct FrustumCulling { FrustumCulling& operator=(FrustumCulling&& rhs) = default; FrustumCulling& operator=(FrustumCulling const& rhs) = default; - ccstd::pmr::unordered_map culledResultIndex; + ccstd::pmr::unordered_map resultIndex; }; struct LightBoundsCullingID { @@ -1308,7 +1308,8 @@ struct SceneCulling { LightBoundsCullingID getOrCreateLightBoundsCulling(const SceneData& sceneData, FrustumCullingID frustumCullingID); NativeRenderQueueID createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); void collectCullingQueries(const RenderGraph& rg, const LayoutGraphData& lg); - void batchCulling(const pipeline::PipelineSceneData& pplSceneData); + void batchFrustumCulling(const pipeline::PipelineSceneData& pplSceneData); + void batchLightBoundsCulling(); void fillRenderQueues(const RenderGraph& rg, const pipeline::PipelineSceneData& pplSceneData); public: ccstd::pmr::unordered_map frustumCullings; diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 741e9b4f903..1fd9b67f8f4 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -49,8 +49,8 @@ FrustumCullingID SceneCulling::getOrCreateFrustumCulling(const SceneData& sceneD }; // find query source - auto iter = queries.culledResultIndex.find(key); - if (iter == queries.culledResultIndex.end()) { + auto iter = queries.resultIndex.find(key); + if (iter == queries.resultIndex.end()) { // create query source // make query source id const FrustumCullingID frustomCulledResultID{numFrustumCulling++}; @@ -61,7 +61,7 @@ FrustumCullingID SceneCulling::getOrCreateFrustumCulling(const SceneData& sceneD } // add query source to query index bool added = false; - std::tie(iter, added) = queries.culledResultIndex.emplace(key, frustomCulledResultID); + std::tie(iter, added) = queries.resultIndex.emplace(key, frustomCulledResultID); CC_ENSURES(added); } return iter->second; @@ -288,13 +288,13 @@ void sceneCulling( } // namespace -void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) { +void SceneCulling::batchFrustumCulling(const pipeline::PipelineSceneData& pplSceneData) { const auto* const skybox = pplSceneData.getSkybox(); const auto* const skyboxModel = skybox && skybox->isEnabled() ? skybox->getModel() : nullptr; for (const auto& [scene, queries] : frustumCullings) { CC_ENSURES(scene); - for (const auto& [key, frustomCulledResultID] : queries.culledResultIndex) { + for (const auto& [key, frustomCulledResultID] : queries.resultIndex) { CC_EXPECTS(key.camera); CC_EXPECTS(key.camera->getScene() == scene); const auto* light = key.light; @@ -372,6 +372,112 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) } namespace { + +void executeSphereLightCulling( + const scene::SphereLight& light, + const ccstd::vector& frustumCullingResult, + ccstd::vector& lightBoundsCullingResult) { + const auto& lightAABB = light.getAABB(); + for (const auto* const model : frustumCullingResult) { + CC_EXPECTS(model); + const auto* const modelBounds = model->getWorldBounds(); + if (!modelBounds || modelBounds->aabbAabb(lightAABB)) { + lightBoundsCullingResult.emplace_back(model); + } + } +} + +void executeSpotLightCulling( + const scene::SpotLight& light, + const ccstd::vector& frustumCullingResult, + ccstd::vector& lightBoundsCullingResult) { + const auto& lightAABB = light.getAABB(); + const auto& lightFrustum = light.getFrustum(); + for (const auto* const model : frustumCullingResult) { + CC_EXPECTS(model); + const auto* const modelBounds = model->getWorldBounds(); + if (!modelBounds || (modelBounds->aabbAabb(lightAABB) && modelBounds->aabbFrustum(lightFrustum))) { + lightBoundsCullingResult.emplace_back(model); + } + } +} + +void executePointLightCulling( + const scene::PointLight& light, + const ccstd::vector& frustumCullingResult, + ccstd::vector& lightBoundsCullingResult) { + const auto& lightAABB = light.getAABB(); + for (const auto* const model : frustumCullingResult) { + CC_EXPECTS(model); + const auto* const modelBounds = model->getWorldBounds(); + if (!modelBounds || modelBounds->aabbAabb(lightAABB)) { + lightBoundsCullingResult.emplace_back(model); + } + } +} + +void executeRangedDirectionalLightCulling( + const scene::RangedDirectionalLight& light, + const ccstd::vector& frustumCullingResult, + ccstd::vector& lightBoundsCullingResult) { + const geometry::AABB rangedDirLightBoundingBox(0.0F, 0.0F, 0.0F, 0.5F, 0.5F, 0.5F); + // when execute render graph, we should never update world matrix + // light->getNode()->updateWorldTransform(); + geometry::AABB lightAABB{}; + rangedDirLightBoundingBox.transform(light.getNode()->getWorldMatrix(), &lightAABB); + for (const auto* const model : frustumCullingResult) { + CC_EXPECTS(model); + const auto* const modelBounds = model->getWorldBounds(); + if (!modelBounds || modelBounds->aabbAabb(lightAABB)) { + lightBoundsCullingResult.emplace_back(model); + } + } +} + +} // namespace + +void SceneCulling::batchLightBoundsCulling() { + for (const auto& [scene, queries] : lightBoundsCullings) { + CC_ENSURES(scene); + for (const auto& [key, cullingID] : queries.resultIndex) { + CC_EXPECTS(key.camera); + CC_EXPECTS(key.camera->getScene() == scene); + const auto& frustumCullingResult = frustumCullingResults.at(key.frustumCullingID.value); + auto& lightBoundsCullingResult = lightBoundsCullingResults.at(cullingID.value); + CC_EXPECTS(lightBoundsCullingResult.empty()); + switch (key.cullingLight->getType()) { + case scene::LightType::SPHERE: { + const auto* light = dynamic_cast(key.cullingLight); + CC_ENSURES(light); + executeSphereLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + } break; + case scene::LightType::SPOT: { + const auto* light = dynamic_cast(key.cullingLight); + CC_ENSURES(light); + executeSpotLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + } break; + case scene::LightType::POINT: { + const auto* light = dynamic_cast(key.cullingLight); + CC_ENSURES(light); + executePointLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + } break; + case scene::LightType::RANGED_DIRECTIONAL: { + const auto* light = dynamic_cast(key.cullingLight); + CC_ENSURES(light); + executeRangedDirectionalLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + } break; + case scene::LightType::DIRECTIONAL: + case scene::LightType::UNKNOWN: + default: + // noop + break; + } + } + } +} + +namespace { + bool isBlend(const scene::Pass& pass) { bool bBlend = false; for (const auto& target : pass.getBlendState()->targets) { @@ -463,6 +569,7 @@ void SceneCulling::fillRenderQueues( for (auto&& [sceneID, desc] : renderQueueIndex) { CC_EXPECTS(holds(sceneID, rg)); const auto frustomCulledResultID = desc.frustumCulledResultID; + const auto lightBoundsCullingID = desc.lightBoundsCulledResultID; const auto targetID = desc.renderQueueTarget; const auto& sceneData = get(SceneTag{}, sceneID, rg); @@ -485,7 +592,16 @@ void SceneCulling::fillRenderQueues( // culling source CC_EXPECTS(frustomCulledResultID.value < frustumCullingResults.size()); - const auto& sourceModels = frustumCullingResults[frustomCulledResultID.value]; + const auto& sourceModels = [&]() -> const auto& { + // is culled by light bounds + if (lightBoundsCullingID.value != 0xFFFFFFFF) { + CC_EXPECTS(lightBoundsCullingID.value < lightBoundsCullingResults.size()); + return lightBoundsCullingResults.at(lightBoundsCullingID.value); + } + // not culled by light bounds + return frustumCullingResults.at(frustomCulledResultID.value); + } + (); // native queue target CC_EXPECTS(targetID.value < renderQueues.size()); @@ -514,7 +630,8 @@ void SceneCulling::buildRenderQueues( pSceneData = &pplSceneData; layoutGraph = ≶ collectCullingQueries(rg, lg); - batchCulling(pplSceneData); + batchFrustumCulling(pplSceneData); + batchLightBoundsCulling(); // cull frustum-culling's results by light bounds fillRenderQueues(rg, pplSceneData); } From ab5b169af5d9193271a4b30cdd06c574e0bbcea3 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 8 Sep 2023 19:01:05 +0800 Subject: [PATCH 56/82] csm updated --- cocos/rendering/custom/pipeline.ts | 11 +- cocos/rendering/custom/web-pipeline.ts | 48 ++++-- .../pipeline/custom/NativeBuiltinUtils.cpp | 137 +++++++++++++-- .../pipeline/custom/NativeBuiltinUtils.h | 18 ++ .../pipeline/custom/NativeExecutor.cpp | 2 +- .../pipeline/custom/NativePipeline.cpp | 1 + .../pipeline/custom/NativePipelineFwd.h | 11 ++ .../pipeline/custom/NativePipelineTypes.h | 157 +++++++++++++++--- .../pipeline/custom/NativeRenderGraph.cpp | 33 +++- .../pipeline/custom/NativeSceneCulling.cpp | 47 ++---- .../renderer/pipeline/custom/NativeSetter.cpp | 10 +- .../pipeline/custom/RenderInterfaceTypes.h | 16 +- native/tools/swig-config/render.i | 3 + 13 files changed, 396 insertions(+), 98 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index b37be952b8a..d0e1960dc6a 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -385,7 +385,10 @@ export interface Setter extends RenderNode { setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void; setBuiltinPointLightConstants (light: PointLight, camera: Camera): void; setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void; - setBuiltinDirectionalLightViewConstants (light: DirectionalLight, level?: number): void; + setBuiltinDirectionalLightViewConstants ( + camera: Camera, + light: DirectionalLight, + level?: number): void; setBuiltinSpotLightViewConstants (light: SpotLight): void; } @@ -413,16 +416,16 @@ export interface RenderQueueBuilder extends Setter { addScene ( camera: Camera, sceneFlags: SceneFlags, - light?: Light | null): void; + light?: Light | null): Setter; addSceneCulledByDirectionalLight ( camera: Camera, sceneFlags: SceneFlags, light: DirectionalLight, - level: number): void; + level: number): Setter; addSceneCulledBySpotLight ( camera: Camera, sceneFlags: SceneFlags, - light: SpotLight): void; + light: SpotLight): Setter; /** * @en Render a full-screen quad. * @zh 渲染全屏四边形 diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 9f915f40c35..a5e7730021b 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -29,7 +29,7 @@ import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency } from './types'; import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; -import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder } from './pipeline'; +import { ComputePassBuilder, ComputeQueueBuilder, BasicPipeline, PipelineBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder, Setter } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight, ProbeType } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; @@ -73,12 +73,17 @@ const _samplerPointInfo = new SamplerInfo( Address.CLAMP, Address.CLAMP, ); -export class WebSetter { +export class WebSetter implements Setter { constructor (data: RenderData, lg: LayoutGraphData) { this._data = data; this._lg = lg; } - + get name (): string { + return ''; + } + set name (name: string) { + // noop + } protected _copyToBuffer (target: IVec4Like | Quat | IVec2Like | IMat4Like | number, offset: number, type: Type): void { assert(offset !== -1); const arr = this.getCurrConstant(); @@ -138,7 +143,7 @@ export class WebSetter { } protected _getCurrUniformBlock (): UniformBlock | undefined { - const block: string = this._currBlock; + const block: string = this._currBlock; const nodeId = this._lg.locateChild(0xFFFFFFFF, this._currStage); const ppl = this._lg.getLayout(nodeId); const layout = ppl.descriptorSets.get(UpdateFrequency.PER_PASS)!.descriptorSetLayoutData; @@ -235,6 +240,9 @@ export class WebSetter { public setFloat (name: string, v: number, idx = 0): void { this._applyCurrConstantBuffer(name, v, Type.FLOAT, idx); } + public setArrayBuffer (name: string, arrayBuffer: ArrayBuffer): void { + throw new Error('Method not implemented.'); + } public offsetFloat (v: number, offset: number): void { this._copyToBuffer(v, offset, Type.FLOAT); } @@ -267,8 +275,8 @@ export class WebSetter { public setBuiltinShadowMapConstants (light: Light, numLevels?: number): void { // TODO } - public setBuiltinDirectionalLightViewConstants (light: DirectionalLight): void { - // TODO + public setBuiltinDirectionalLightViewConstants (camera: Camera, light: DirectionalLight, level = 0): void { + setShadowUBOLightView(this, camera, light, level); } public setBuiltinSpotLightViewConstants (light: SpotLight): void { // TODO @@ -307,7 +315,7 @@ export class WebSetter { } // protected - protected _data: RenderData; + protected _data: RenderData; protected _lg: LayoutGraphData; protected _currBlock; protected _currStage: string = ''; @@ -816,7 +824,7 @@ function setTextureUBOView (setter: WebSetter, camera: Camera | null, cfg: Reado setter.setSampler('cc_spotShadowMap', pipeline.defaultSampler); } if (!setter.hasTexture('cc_spotShadowMap')) { - setter.setTexture('cc_spotShadowMap', pipeline.defaultTexture); + setter.setTexture('cc_spotShadowMap', pipeline.defaultTexture); } } @@ -864,7 +872,7 @@ function getResourceDimension (type: TextureType): ResourceDimension { return ResourceDimension.TEXTURE2D; } -export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuilder { +export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuilder { constructor (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, vertID: number, queue: RenderQueue, pipeline: PipelineSceneData) { super(data, layoutGraph); this._renderGraph = renderGraph; @@ -908,17 +916,23 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild setTextureUBOView(this, camera, this._pipeline); initGlobalDescBinding(this._data, layoutName); } - addScene (camera: Camera, sceneFlags = SceneFlags.NONE): void { + addScene (camera: Camera, sceneFlags = SceneFlags.NONE): Setter { const sceneData = new SceneData(camera.scene, camera, sceneFlags); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', new RenderData(), false, this._vertID); + const renderData = new RenderData(); + this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); + return new WebSetter(renderData, this._lg); } - addSceneCulledByDirectionalLight (camera: Camera, sceneFlags: SceneFlags, light: DirectionalLight, level: number): void { + addSceneCulledByDirectionalLight (camera: Camera, sceneFlags: SceneFlags, light: DirectionalLight, level: number): Setter { const sceneData = new SceneData(camera.scene, camera, sceneFlags, new LightInfo(light, level)); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', new RenderData(), false, this._vertID); + const renderData = new RenderData(); + this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); + return new WebSetter(renderData, this._lg); } - addSceneCulledBySpotLight (camera: Camera, sceneFlags: SceneFlags, light: SpotLight): void { + addSceneCulledBySpotLight (camera: Camera, sceneFlags: SceneFlags, light: SpotLight): Setter { const sceneData = new SceneData(camera.scene, camera, sceneFlags, new LightInfo(light, 0)); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', new RenderData(), false, this._vertID); + const renderData = new RenderData(); + this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); + return new WebSetter(renderData, this._lg); } addFullscreenQuad (material: Material, passID: number, sceneFlags = SceneFlags.NONE, name = 'Quad'): void { this._renderGraph.addVertex( @@ -1411,7 +1425,7 @@ export class WebCopyPassBuilder { function isManaged (residency: ResourceResidency): boolean { return residency === ResourceResidency.MANAGED - || residency === ResourceResidency.MEMORYLESS; + || residency === ResourceResidency.MEMORYLESS; } export class WebPipeline implements BasicPipeline { @@ -1717,7 +1731,7 @@ export class WebPipeline implements BasicPipeline { this.setMacroInt('CC_DIR_LIGHT_SHADOW_TYPE', 0); // 0: CC_CASCADED_LAYERS_TRANSITION_OFF, 1: CC_CASCADED_LAYERS_TRANSITION_ON - this.setMacroBool('CC_CASCADED_LAYERS_TRANSITION', false); + this.setMacroBool('CC_CASCADED_LAYERS_TRANSITION', false); // enable the deferred pipeline if (this.usesDeferredPipeline) { diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp index 07c7d0aaa33..e04a21800b3 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp @@ -28,12 +28,15 @@ #include "cocos/renderer/gfx-base/GFXDevice.h" #include "cocos/renderer/pipeline/PipelineSceneData.h" #include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" +#include "cocos/renderer/pipeline/custom/NativePipelineTypes.h" #include "cocos/renderer/pipeline/custom/NativeTypes.h" #include "cocos/renderer/pipeline/custom/NativeUtils.h" #include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" #include "cocos/scene/Camera.h" +#include "cocos/scene/DirectionalLight.h" #include "cocos/scene/Fog.h" +#include "cocos/scene/Shadow.h" #include "cocos/scene/Skybox.h" #include "cocos/scene/SpotLight.h" @@ -390,11 +393,11 @@ void setShadowUBOLightView( gfx::Device *device, const LayoutGraphData &layoutGraph, const pipeline::PipelineSceneData &sceneData, + const BuiltinCascadedShadowMap *csm, const scene::Light &light, uint32_t level, RenderData &data) { const auto &shadowInfo = *sceneData.getShadows(); - const auto &csmLayers = *sceneData.getCSMLayers(); const auto &packing = pipeline::supportsR32FloatTexture(device) ? 0.0F : 1.0F; const auto &cap = device->getCapabilities(); Vec4 vec4ShadowInfo{}; @@ -411,29 +414,31 @@ void setShadowUBOLightView( Mat4 matShadowProj; Mat4 matShadowViewProj; scene::CSMLevel levelCount{}; + CC_EXPECTS(csm); if (mainLight.isShadowFixedArea() || mainLight.getCSMLevel() == scene::CSMLevel::LEVEL_1) { - matShadowView = csmLayers.getSpecialLayer()->getMatShadowView(); - matShadowProj = csmLayers.getSpecialLayer()->getMatShadowProj(); - matShadowViewProj = csmLayers.getSpecialLayer()->getMatShadowViewProj(); + matShadowView = csm->specialLayer.shadowView; + matShadowProj = csm->specialLayer.shadowProj; + matShadowViewProj = csm->specialLayer.shadowViewProj; if (mainLight.isShadowFixedArea()) { near = mainLight.getShadowNear(); far = mainLight.getShadowFar(); levelCount = static_cast(0); } else { near = 0.1F; - far = csmLayers.getSpecialLayer()->getShadowCameraFar(); + far = csm->specialLayer.shadowCameraFar; levelCount = scene::CSMLevel::LEVEL_1; } vec4ShadowInfo.set(static_cast(scene::LightType::DIRECTIONAL), packing, mainLight.getShadowNormalBias(), 0); setVec4Impl(data, layoutGraph, "cc_shadowLPNNInfo", vec4ShadowInfo); } else { - const auto &layer = *csmLayers.getLayers()[level]; - matShadowView = layer.getMatShadowView(); - matShadowProj = layer.getMatShadowProj(); - matShadowViewProj = layer.getMatShadowViewProj(); - - near = layer.getSplitCameraNear(); - far = layer.getSplitCameraFar(); + CC_EXPECTS(level < csm->layers.size()); + const auto &layer = csm->layers[level]; + matShadowView = layer.shadowView; + matShadowProj = layer.shadowProj; + matShadowViewProj = layer.shadowViewProj; + + near = layer.splitCameraNear; + far = layer.splitCameraFar; levelCount = mainLight.getCSMLevel(); } setMat4Impl(data, layoutGraph, "cc_matLightView", matShadowView); @@ -552,6 +557,114 @@ void setLegacyTextureUBOView( // setTextureImpl(data, layoutGraph, "cc_spotShadowMap", BuiltinResMgr::getInstance()->get("default-texture")->getGFXTexture()); } +const BuiltinCascadedShadowMap *getBuiltinShadowCSM( + const PipelineRuntime &pplRuntime, + const scene::Camera &camera, + const scene::DirectionalLight *mainLight) { + const auto &ppl = dynamic_cast(pplRuntime); + // no main light + if (!mainLight) { + return nullptr; + } + // not attached to a node + if (!mainLight->getNode()) { + return nullptr; + } + const pipeline::PipelineSceneData &pplSceneData = *pplRuntime.getPipelineSceneData(); + auto &csmLayers = *pplSceneData.getCSMLayers(); + const auto &shadows = *pplSceneData.getShadows(); + // shadow not enabled + if (!shadows.isEnabled()) { + return nullptr; + } + // shadow type is planar + if (shadows.getType() == scene::ShadowType::PLANAR) { + return nullptr; + } + + // find csm + const BuiltinCascadedShadowMapKey key{&camera, mainLight}; + auto iter = ppl.builtinCSMs.find(key); + if (iter != ppl.builtinCSMs.end()) { + return &iter->second; + } + + // add new csm info + bool added = false; + std::tie(iter, added) = ppl.builtinCSMs.emplace( + std::piecewise_construct, + std::forward_as_tuple(key), + std::forward_as_tuple()); + CC_ENSURES(added); + + auto &csm = iter->second; + + // update csm layers + csmLayers.update(&pplSceneData, &camera); + + // copy csm data + CC_EXPECTS(csm.layers.size() == csmLayers.getLayers().size()); + for (uint32_t i = 0; i != csm.layers.size(); ++i) { + const auto &src = *csmLayers.getLayers()[i]; + auto &dst = csm.layers[i]; + dst.shadowView = src.getMatShadowView(); + dst.shadowProj = src.getMatShadowProj(); + dst.shadowViewProj = src.getMatShadowViewProj(); + dst.validFrustum = src.getValidFrustum(); + dst.splitFrustum = src.getSplitFrustum(); + dst.lightViewFrustum = src.getLightViewFrustum(); + dst.castLightViewBoundingBox = src.getCastLightViewBoundingBox(); + dst.shadowCameraFar = src.getShadowCameraFar(); + dst.splitCameraNear = src.getSplitCameraNear(); + dst.splitCameraFar = src.getSplitCameraFar(); + dst.csmAtlas = src.getCSMAtlas(); + } + + { + const auto &src = *csmLayers.getSpecialLayer(); + auto &dst = csm.specialLayer; + dst.shadowView = src.getMatShadowView(); + dst.shadowProj = src.getMatShadowProj(); + dst.shadowViewProj = src.getMatShadowViewProj(); + dst.validFrustum = src.getValidFrustum(); + dst.splitFrustum = src.getSplitFrustum(); + dst.lightViewFrustum = src.getLightViewFrustum(); + dst.castLightViewBoundingBox = src.getCastLightViewBoundingBox(); + dst.shadowCameraFar = src.getShadowCameraFar(); + } + + csm.shadowDistance = mainLight->getShadowDistance(); + + return &csm; +} + +const geometry::Frustum &getBuiltinShadowFrustum( + const PipelineRuntime &pplRuntime, + const scene::Camera &camera, + const scene::DirectionalLight *mainLight, + uint32_t level) { + const auto &ppl = dynamic_cast(pplRuntime); + + const auto &shadows = *ppl.pipelineSceneData->getShadows(); + if (shadows.getType() == scene::ShadowType::PLANAR) { + return camera.getFrustum(); + } + + BuiltinCascadedShadowMapKey key{&camera, mainLight}; + auto iter = ppl.builtinCSMs.find(key); + if (iter == ppl.builtinCSMs.end()) { + throw std::runtime_error("Builtin shadow CSM not found"); + } + + const auto &csmLevel = mainLight->getCSMLevel(); + const auto &csm = iter->second; + + if (mainLight->isShadowFixedArea() || csmLevel == scene::CSMLevel::LEVEL_1) { + return csm.specialLayer.validFrustum; + } + return csm.layers[level].validFrustum; +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h index e3f316085f2..1b1d8ebb6a2 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h @@ -28,6 +28,7 @@ #include "cocos/renderer/gfx-base/GFXDevice.h" #include "cocos/renderer/pipeline/custom/LayoutGraphFwd.h" #include "cocos/renderer/pipeline/custom/NativeFwd.h" +#include "cocos/renderer/pipeline/custom/NativePipelineFwd.h" #include "cocos/renderer/pipeline/custom/RenderGraphFwd.h" namespace cc { @@ -38,6 +39,10 @@ class Light; class DirectionalLight; } // namespace scene +namespace geometry { +class Frustum; +} // namespace geometry + namespace gfx { class Device; } // namespace gfx @@ -74,6 +79,7 @@ void setShadowUBOLightView( gfx::Device *device, const LayoutGraphData &layoutGraph, const pipeline::PipelineSceneData &sceneData, + const BuiltinCascadedShadowMap *csm, const scene::Light &light, uint32_t level, RenderData &data); @@ -84,6 +90,18 @@ void updateRasterPassConstants(uint32_t width, uint32_t height, Setter &setter); // Geometry void setupQuadVertexBuffer(gfx::Device &device, const Vec4 &viewport, float vbData[16]); +// Shadow +const BuiltinCascadedShadowMap *getBuiltinShadowCSM( + const PipelineRuntime &pplRuntime, + const scene::Camera &camera, + const scene::DirectionalLight *mainLight); + +const geometry::Frustum &getBuiltinShadowFrustum( + const PipelineRuntime &pplRuntime, + const scene::Camera &camera, + const scene::DirectionalLight *mainLight, + uint32_t level); + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 6d0a2b659a5..7d77b7c2281 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -1985,7 +1985,7 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { { auto& context = ppl.nativeContext; auto& sceneCulling = context.sceneCulling; - sceneCulling.buildRenderQueues(rg, lg, *ppl.pipelineSceneData); + sceneCulling.buildRenderQueues(rg, lg, ppl); auto& group = ppl.nativeContext.resourceGroups[context.nextFenceValue]; // notice: we cannot use ranged-for of sceneCulling.renderQueues CC_EXPECTS(sceneCulling.numRenderQueues <= sceneCulling.renderQueues.size()); diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index ad31201328f..da2643078ad 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -123,6 +123,7 @@ PipelineCapabilities NativePipeline::getCapabilities() const { void NativePipeline::beginSetup() { renderGraph = RenderGraph(get_allocator()); + builtinCSMs.clear(); } void NativePipeline::endSetup() { diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index dc124395c27..1860969b097 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -40,6 +40,13 @@ class ReflectionProbe; } // namespace scene +namespace render { + +template +using Array4 = std::array; + +} // namespace render + } // namespace cc #include "cocos/base/std/hash/hash.h" @@ -50,6 +57,7 @@ namespace render { class NativeRenderNode; class NativeSetter; +class NativeSetterBuilder; class NativeRenderSubpassBuilderImpl; class NativeRenderQueueBuilder; class NativeRenderSubpassBuilder; @@ -87,6 +95,9 @@ struct SceneCulling; struct NativeRenderContext; class NativeProgramLibrary; struct PipelineCustomization; +struct BuiltinShadowTransform; +struct BuiltinCascadedShadowMapKey; +struct BuiltinCascadedShadowMap; class NativePipeline; class NativeProgramProxy; class NativeRenderingModule; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 46736baaaa5..cfe8ccd47fe 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -33,6 +33,8 @@ #include "cocos/base/Ptr.h" #include "cocos/base/std/container/string.h" #include "cocos/base/std/hash/hash.h" +#include "cocos/core/geometry/AABB.h" +#include "cocos/core/geometry/Frustum.h" #include "cocos/renderer/gfx-base/GFXFramebuffer.h" #include "cocos/renderer/gfx-base/GFXRenderPass.h" #include "cocos/renderer/pipeline/GlobalDescriptorSetManager.h" @@ -94,7 +96,7 @@ class NativeSetter : public NativeRenderNode { void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) /*implements*/; void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) /*implements*/; void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) /*implements*/; - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) /*implements*/; + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) /*implements*/; void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) /*implements*/; void setVec4ArraySize(const ccstd::string& name, uint32_t sz); @@ -107,6 +109,86 @@ class NativeSetter : public NativeRenderNode { uint32_t layoutID{LayoutGraphData::null_vertex()}; }; +class NativeSetterBuilder final : public Setter, public NativeSetter { +public: + NativeSetterBuilder(const PipelineRuntime* pipelineRuntimeIn, RenderGraph* renderGraphIn, uint32_t nodeIDIn, const LayoutGraphData* layoutGraphIn, uint32_t layoutIDIn) noexcept + : NativeSetter(pipelineRuntimeIn, renderGraphIn, nodeIDIn, layoutGraphIn, layoutIDIn) {} + + ccstd::string getName() const override { + return NativeRenderNode::getName(); + } + void setName(const ccstd::string &name) override { + NativeRenderNode::setName(name); + } + void setCustomBehavior(const ccstd::string &name) override { + NativeRenderNode::setCustomBehavior(name); + } + + void setMat4(const ccstd::string &name, const Mat4 &mat) override { + NativeSetter::setMat4(name, mat); + } + void setQuaternion(const ccstd::string &name, const Quaternion &quat) override { + NativeSetter::setQuaternion(name, quat); + } + void setColor(const ccstd::string &name, const gfx::Color &color) override { + NativeSetter::setColor(name, color); + } + void setVec4(const ccstd::string &name, const Vec4 &vec) override { + NativeSetter::setVec4(name, vec); + } + void setVec2(const ccstd::string &name, const Vec2 &vec) override { + NativeSetter::setVec2(name, vec); + } + void setFloat(const ccstd::string &name, float v) override { + NativeSetter::setFloat(name, v); + } + void setArrayBuffer(const ccstd::string &name, const ArrayBuffer *arrayBuffer) override { + NativeSetter::setArrayBuffer(name, arrayBuffer); + } + void setBuffer(const ccstd::string &name, gfx::Buffer *buffer) override { + NativeSetter::setBuffer(name, buffer); + } + void setTexture(const ccstd::string &name, gfx::Texture *texture) override { + NativeSetter::setTexture(name, texture); + } + void setReadWriteBuffer(const ccstd::string &name, gfx::Buffer *buffer) override { + NativeSetter::setReadWriteBuffer(name, buffer); + } + void setReadWriteTexture(const ccstd::string &name, gfx::Texture *texture) override { + NativeSetter::setReadWriteTexture(name, texture); + } + void setSampler(const ccstd::string &name, gfx::Sampler *sampler) override { + NativeSetter::setSampler(name, sampler); + } + void setBuiltinCameraConstants(const scene::Camera *camera) override { + NativeSetter::setBuiltinCameraConstants(camera); + } + void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { + NativeSetter::setBuiltinShadowMapConstants(light); + } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + } + void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightViewConstants(light); + } +}; + class NativeRenderSubpassBuilderImpl : public NativeSetter { public: NativeRenderSubpassBuilderImpl(const PipelineRuntime* pipelineRuntimeIn, RenderGraph* renderGraphIn, uint32_t nodeIDIn, const LayoutGraphData* layoutGraphIn, uint32_t layoutIDIn) @@ -196,17 +278,17 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); } void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) override; - void addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) override; - void addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) override; - void addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) override; + Setter *addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) override; + Setter *addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) override; + Setter *addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) 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; @@ -286,8 +368,8 @@ class NativeRenderSubpassBuilder final : public RenderSubpassBuilder, public Nat void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -397,8 +479,8 @@ class NativeMultisampleRenderSubpassBuilder final : public MultisampleRenderSubp void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -511,8 +593,8 @@ class NativeComputeSubpassBuilder final : public ComputeSubpassBuilder, public N void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -598,8 +680,8 @@ class NativeRenderPassBuilder final : public RenderPassBuilder, public NativeSet void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -697,8 +779,8 @@ class NativeMultisampleRenderPassBuilder final : public MultisampleRenderPassBui void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -795,8 +877,8 @@ class NativeComputeQueueBuilder final : public ComputeQueueBuilder, public Nativ void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -877,8 +959,8 @@ class NativeComputePassBuilder final : public ComputePassBuilder, public NativeS void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { + NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); } void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { NativeSetter::setBuiltinSpotLightViewConstants(light); @@ -1302,13 +1384,13 @@ struct SceneCulling { SceneCulling& operator=(SceneCulling const& rhs) = delete; void clear() noexcept; - void buildRenderQueues(const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData); + void buildRenderQueues(const RenderGraph& rg, const LayoutGraphData& lg, const NativePipeline& ppl); private: FrustumCullingID getOrCreateFrustumCulling(const SceneData& sceneData); LightBoundsCullingID getOrCreateLightBoundsCulling(const SceneData& sceneData, FrustumCullingID frustumCullingID); NativeRenderQueueID createRenderQueue(SceneFlags sceneFlags, LayoutGraphData::vertex_descriptor subpassOrPassLayoutID); void collectCullingQueries(const RenderGraph& rg, const LayoutGraphData& lg); - void batchFrustumCulling(const pipeline::PipelineSceneData& pplSceneData); + void batchFrustumCulling(const NativePipeline& ppl); void batchLightBoundsCulling(); void fillRenderQueues(const RenderGraph& rg, const pipeline::PipelineSceneData& pplSceneData); public: @@ -1414,6 +1496,36 @@ struct PipelineCustomization { PmrTransparentMap> renderCommands; }; +struct BuiltinShadowTransform { + Mat4 shadowView; + Mat4 shadowProj; + Mat4 shadowViewProj; + geometry::Frustum validFrustum; + geometry::Frustum splitFrustum; + geometry::Frustum lightViewFrustum; + geometry::AABB castLightViewBoundingBox; + float shadowCameraFar{0}; + float splitCameraNear{0}; + float splitCameraFar{0}; + Vec4 csmAtlas; +}; + +struct BuiltinCascadedShadowMapKey { + const scene::Camera* camera{nullptr}; + const scene::DirectionalLight* light{nullptr}; +}; + +inline bool operator<(const BuiltinCascadedShadowMapKey& lhs, const BuiltinCascadedShadowMapKey& rhs) noexcept { + return std::forward_as_tuple(lhs.camera, lhs.light) < + std::forward_as_tuple(rhs.camera, rhs.light); +} + +struct BuiltinCascadedShadowMap { + Array4 layers; + BuiltinShadowTransform specialLayer; + float shadowDistance{0}; +}; + class NativePipeline final : public Pipeline { public: using allocator_type = boost::container::pmr::polymorphic_allocator; @@ -1525,6 +1637,7 @@ class NativePipeline final : public Pipeline { NativeRenderContext nativeContext; ResourceGraph resourceGraph; RenderGraph renderGraph; + mutable PmrFlatMap builtinCSMs; PipelineStatistics statistics; PipelineCustomization custom; }; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 07a18b68f0f..8974aaa4255 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -729,12 +729,18 @@ void NativeRenderQueueBuilder::addSceneOfCamera( *pipelineRuntime->getPipelineSceneData(), camera->getScene()->getMainLight(), data); + // notice: if light is not directional light, csm will be nullptr + const auto *csm = getBuiltinShadowCSM( + *pipelineRuntime, *camera, + dynamic_cast(pLight)); + if (any(sceneFlags & SceneFlags::SHADOW_CASTER)) { if (pLight) { setShadowUBOLightView( pipelineRuntime->getDevice(), *layoutGraph, *pipelineRuntime->getPipelineSceneData(), + csm, // csm might be nullptr *pLight, light.level, data); } } else { @@ -753,7 +759,7 @@ void NativeRenderQueueBuilder::addSceneOfCamera( data); } -void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { +Setter *NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { auto cullingFlags = CullingFlags::CAMERA_FRUSTUM; if (light) { cullingFlags |= CullingFlags::LIGHT_BOUNDS; @@ -805,9 +811,16 @@ void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags } } } + + return new NativeSetterBuilder( + pipelineRuntime, + renderGraph, + sceneID, + layoutGraph, + layoutID); } -void NativeRenderQueueBuilder::addSceneCulledByDirectionalLight( +Setter *NativeRenderQueueBuilder::addSceneCulledByDirectionalLight( const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) { CC_EXPECTS(light); @@ -823,9 +836,16 @@ void NativeRenderQueueBuilder::addSceneCulledByDirectionalLight( std::forward_as_tuple(std::move(data)), *renderGraph, nodeID); CC_ENSURES(sceneID != RenderGraph::null_vertex()); + + return new NativeSetterBuilder( + pipelineRuntime, + renderGraph, + sceneID, + layoutGraph, + layoutID); } -void NativeRenderQueueBuilder::addSceneCulledBySpotLight( +Setter *NativeRenderQueueBuilder::addSceneCulledBySpotLight( const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) { CC_EXPECTS(light); @@ -841,6 +861,13 @@ void NativeRenderQueueBuilder::addSceneCulledBySpotLight( std::forward_as_tuple(std::move(data)), *renderGraph, nodeID); CC_ENSURES(sceneID != RenderGraph::null_vertex()); + + return new NativeSetterBuilder( + pipelineRuntime, + renderGraph, + sceneID, + layoutGraph, + layoutID); } void NativeRenderQueueBuilder::addFullscreenQuad( diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 1fd9b67f8f4..84018297d42 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -1,4 +1,5 @@ #include "cocos/renderer/pipeline/Define.h" +#include "cocos/renderer/pipeline/custom/NativeBuiltinUtils.h" #include "cocos/renderer/pipeline/custom/NativePipelineTypes.h" #include "cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" @@ -156,8 +157,11 @@ void SceneCulling::collectCullingQueries( } namespace { -const pipeline::PipelineSceneData* pSceneData = nullptr; -const LayoutGraphData* layoutGraph = nullptr; + +const pipeline::PipelineSceneData* kPipelineSceneData = nullptr; + +const LayoutGraphData* kLayoutGraph = nullptr; + bool isNodeVisible(const Node* node, uint32_t visibility) { return node && ((visibility & node->getLayer()) == node->getLayer()); } @@ -181,7 +185,7 @@ bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustu } geometry::AABB transWorldBounds{}; transWorldBounds.set(modelWorldBounds->getCenter(), modelWorldBounds->getHalfExtents()); - const scene::Shadows& shadows = *pSceneData->getShadows(); + const scene::Shadows& shadows = *kPipelineSceneData->getShadows(); if (shadows.getType() == scene::ShadowType::PLANAR && castShadow) { modelWorldBounds->transform(shadows.getMatLight(), &transWorldBounds); } @@ -288,7 +292,8 @@ void sceneCulling( } // namespace -void SceneCulling::batchFrustumCulling(const pipeline::PipelineSceneData& pplSceneData) { +void SceneCulling::batchFrustumCulling(const NativePipeline& ppl) { + const auto& pplSceneData = *ppl.getPipelineSceneData(); const auto* const skybox = pplSceneData.getSkybox(); const auto* const skyboxModel = skybox && skybox->isEnabled() ? skybox->getModel() : nullptr; @@ -328,28 +333,12 @@ void SceneCulling::batchFrustumCulling(const pipeline::PipelineSceneData& pplSce models); break; case scene::LightType::DIRECTIONAL: { - auto& csmLayers = *pplSceneData.getCSMLayers(); const auto* mainLight = dynamic_cast(light); - const auto& csmLevel = mainLight->getCSMLevel(); - const geometry::Frustum* frustum = nullptr; - const auto& shadows = *pplSceneData.getShadows(); - if (shadows.getType() == scene::ShadowType::PLANAR) { - frustum = &camera.getFrustum(); - } else { - if (shadows.isEnabled() && shadows.getType() == scene::ShadowType::SHADOW_MAP && mainLight && mainLight->getNode()) { - csmLayers.update(&pplSceneData, &camera); - } - // const - if (mainLight->isShadowFixedArea() || csmLevel == scene::CSMLevel::LEVEL_1) { - frustum = &csmLayers.getSpecialLayer()->getValidFrustum(); - } else { - frustum = &csmLayers.getLayers()[level]->getValidFrustum(); - } - } + const auto& frustum = getBuiltinShadowFrustum(ppl, camera, mainLight, level); sceneCulling( skyboxModel, *scene, camera, - *frustum, + frustum, bCastShadow, nullptr, models); @@ -509,7 +498,7 @@ void addRenderObject( const scene::Model& model, NativeRenderQueue& queue) { if (bDrawProbe) { - queue.probeQueue.applyMacro(*layoutGraph, model, phaseLayoutID); + queue.probeQueue.applyMacro(*kLayoutGraph, model, phaseLayoutID); } const auto& subModels = model.getSubModels(); const auto subModelCount = subModels.size(); @@ -519,7 +508,7 @@ void addRenderObject( const auto passCount = passes.size(); auto probeIt = std::find(queue.probeQueue.probeMap.begin(), queue.probeQueue.probeMap.end(), subModel.get()); if (probeIt != queue.probeQueue.probeMap.end()) { - phaseLayoutID = ProbeHelperQueue::getDefaultId(*layoutGraph); + phaseLayoutID = ProbeHelperQueue::getDefaultId(*kLayoutGraph); } for (uint32_t passIdx = 0; passIdx < passCount; ++passIdx) { auto& pass = *passes[passIdx]; @@ -626,13 +615,13 @@ void SceneCulling::fillRenderQueues( void SceneCulling::buildRenderQueues( const RenderGraph& rg, const LayoutGraphData& lg, - const pipeline::PipelineSceneData& pplSceneData) { - pSceneData = &pplSceneData; - layoutGraph = ≶ + const NativePipeline& ppl) { + kPipelineSceneData = ppl.pipelineSceneData; + kLayoutGraph = ≶ collectCullingQueries(rg, lg); - batchFrustumCulling(pplSceneData); + batchFrustumCulling(ppl); batchLightBoundsCulling(); // cull frustum-culling's results by light bounds - fillRenderQueues(rg, pplSceneData); + fillRenderQueues(rg, *ppl.pipelineSceneData); } void SceneCulling::clear() noexcept { diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index 3fa33ea6a81..0ff02f007b7 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -124,12 +124,18 @@ void NativeSetter::setBuiltinCameraConstants(const scene::Camera *camera) { } void NativeSetter::setBuiltinDirectionalLightViewConstants( + const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) { CC_EXPECTS(light); + // if csm is actually activated, csm is not nullptr + // update and get csm + const auto *csm = getBuiltinShadowCSM(*pipelineRuntime, *camera, light); + + // set data auto *device = pipelineRuntime->getDevice(); const auto &sceneData = *pipelineRuntime->getPipelineSceneData(); auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); - setShadowUBOLightView(device, *layoutGraph, sceneData, *light, level, data); + setShadowUBOLightView(device, *layoutGraph, sceneData, csm, *light, level, data); } void NativeSetter::setBuiltinSpotLightViewConstants(const scene::SpotLight *light) { @@ -137,7 +143,7 @@ void NativeSetter::setBuiltinSpotLightViewConstants(const scene::SpotLight *ligh auto *device = pipelineRuntime->getDevice(); const auto &sceneData = *pipelineRuntime->getPipelineSceneData(); auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); - setShadowUBOLightView(device, *layoutGraph, sceneData, *light, 0, data); + setShadowUBOLightView(device, *layoutGraph, sceneData, nullptr, *light, 0, data); } void NativeSetter::setBuiltinShadowMapConstants( diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 531886bda52..3e2078df625 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -460,10 +460,10 @@ class Setter : public RenderNode { virtual void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) = 0; virtual void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) = 0; virtual void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) = 0; - virtual void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) = 0; + virtual void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) = 0; virtual void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) = 0; - void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light) { - setBuiltinDirectionalLightViewConstants(light, 0); + void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light) { + setBuiltinDirectionalLightViewConstants(camera, light, 0); } }; @@ -488,9 +488,9 @@ class RenderQueueBuilder : public Setter { * @param sceneFlags @en Rendering flags of the scene @zh 场景渲染标志位 */ virtual void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) = 0; - virtual void addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) = 0; - virtual void addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) = 0; - virtual void addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) = 0; + virtual Setter *addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) = 0; + virtual Setter *addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) = 0; + virtual Setter *addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) = 0; /** * @en Render a full-screen quad. * @zh 渲染全屏四边形 @@ -528,8 +528,8 @@ class RenderQueueBuilder : public Setter { void addSceneOfCamera(scene::Camera *camera, LightInfo light) { addSceneOfCamera(camera, std::move(light), SceneFlags::NONE); } - void addScene(const scene::Camera *camera, SceneFlags sceneFlags) { - addScene(camera, sceneFlags, nullptr); + Setter *addScene(const scene::Camera *camera, SceneFlags sceneFlags) { + return addScene(camera, sceneFlags, nullptr); } void addFullscreenQuad(Material *material, uint32_t passID) { addFullscreenQuad(material, passID, SceneFlags::NONE); diff --git a/native/tools/swig-config/render.i b/native/tools/swig-config/render.i index dbaf304bec1..044b59f10e7 100644 --- a/native/tools/swig-config/render.i +++ b/native/tools/swig-config/render.i @@ -81,6 +81,9 @@ using namespace cc::render; %release_returned_cpp_object_in_gc(cc::render::RenderPassBuilder::addMultisampleRenderSubpass); %release_returned_cpp_object_in_gc(cc::render::RenderPassBuilder::addComputeSubpass); %release_returned_cpp_object_in_gc(cc::render::ComputePassBuilder::addQueue); +%release_returned_cpp_object_in_gc(cc::render::RenderQueueBuilder::addScene); +%release_returned_cpp_object_in_gc(cc::render::RenderQueueBuilder::addSceneCulledByDirectionalLight); +%release_returned_cpp_object_in_gc(cc::render::RenderQueueBuilder::addSceneCulledBySpotLight); %release_returned_cpp_object_in_gc(cc::render::Pipeline::addRenderPass); %release_returned_cpp_object_in_gc(cc::render::Pipeline::addComputePass); From a8375b71e67467e98e864707f702694ac33fad4e Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Mon, 11 Sep 2023 18:22:55 +0800 Subject: [PATCH 57/82] fix compile error --- cocos/rendering/custom/executor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index affb95d722a..15079212cf2 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1692,6 +1692,7 @@ class ExecutorPools { readonly computeQueuePool: RecyclePool; readonly graphScenePool: RecyclePool; readonly reflectionProbe: RecyclePool; + readonly passPool: RecyclePool; readonly rasterPassInfoPool: RecyclePool; readonly computePassInfoPool: RecyclePool; } From 7bb1c99d566773ee76c323c51782cad6f81321b6 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 12 Sep 2023 11:37:09 +0800 Subject: [PATCH 58/82] addScene simplified --- cocos/rendering/custom/pipeline.ts | 40 +++--- cocos/rendering/custom/private.ts | 2 +- cocos/rendering/custom/render-graph.ts | 40 +++++- cocos/rendering/custom/types.ts | 1 + cocos/rendering/custom/web-pipeline.ts | 91 +++++++++---- .../pipeline/custom/FrameGraphDispatcher.cpp | 6 +- .../pipeline/custom/NativePipelineFwd.h | 2 +- .../pipeline/custom/NativePipelineTypes.h | 86 ++++++------ .../pipeline/custom/NativeRenderGraph.cpp | 123 +++++++++--------- .../pipeline/custom/NativeResourceGraph.cpp | 8 +- .../renderer/pipeline/custom/NativeSetter.cpp | 4 +- .../pipeline/custom/RenderCommonTypes.h | 1 + .../renderer/pipeline/custom/RenderGraphFwd.h | 2 + .../pipeline/custom/RenderGraphGraphs.h | 56 ++++---- .../pipeline/custom/RenderGraphTypes.h | 28 +++- .../pipeline/custom/RenderInterfaceFwd.h | 1 + .../pipeline/custom/RenderInterfaceTypes.h | 27 ++-- native/tools/swig-config/render.i | 2 - package-lock.json | 4 +- 19 files changed, 311 insertions(+), 213 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index d0e1960dc6a..c749445f4f7 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -119,13 +119,13 @@ export interface PipelineRuntime { * This model is used to render profile information in Debug mode. * @zh 获得分析工具(Profiler)的渲染实例,用于Debug模式下显示调试与性能检测信息 */ - profiler: Model | null; + profiler: Model | undefined; /** * @en Get geometry renderer. * Geometry renderer is used to render procedural geometries. * @zh 获得几何渲染器(GeometryRenderer),几何渲染器用于程序化渲染基础几何图形 */ - readonly geometryRenderer: GeometryRenderer | null; + readonly geometryRenderer: GeometryRenderer | undefined; /** * @en Get shading scale. * Shading scale affects shading texels per pixel. @@ -385,11 +385,18 @@ export interface Setter extends RenderNode { setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void; setBuiltinPointLightConstants (light: PointLight, camera: Camera): void; setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void; - setBuiltinDirectionalLightViewConstants ( + setBuiltinDirectionalLightFrustumConstants ( camera: Camera, light: DirectionalLight, - level?: number): void; - setBuiltinSpotLightViewConstants (light: SpotLight): void; + csmLevel?: number): void; + setBuiltinSpotLightFrustumConstants (light: SpotLight): void; +} + +export interface SceneBuilder extends Setter { + useLightFrustum ( + light: Light, + csmLevel?: number, + optCamera?: Camera): void; } /** @@ -416,16 +423,7 @@ export interface RenderQueueBuilder extends Setter { addScene ( camera: Camera, sceneFlags: SceneFlags, - light?: Light | null): Setter; - addSceneCulledByDirectionalLight ( - camera: Camera, - sceneFlags: SceneFlags, - light: DirectionalLight, - level: number): Setter; - addSceneCulledBySpotLight ( - camera: Camera, - sceneFlags: SceneFlags, - light: SpotLight): Setter; + light?: Light): SceneBuilder; /** * @en Render a full-screen quad. * @zh 渲染全屏四边形 @@ -518,7 +516,7 @@ export interface BasicRenderPassBuilder extends Setter { addTexture ( name: string, slotName: string, - sampler?: Sampler | null, + sampler?: Sampler, plane?: number): void; /** * @en Add render queue. @@ -817,7 +815,7 @@ export interface BasicPipeline extends PipelineRuntime { /** * @engineInternal */ - getDescriptorSetLayout (shaderName: string, freq: UpdateFrequency): DescriptorSetLayout | null; + getDescriptorSetLayout (shaderName: string, freq: UpdateFrequency): DescriptorSetLayout | undefined; } /** @@ -880,7 +878,7 @@ export interface RenderSubpassBuilder extends Setter { addTexture ( name: string, slotName: string, - sampler?: Sampler | null, + sampler?: Sampler, plane?: number): void; /** * @en Add storage buffer. @@ -1024,7 +1022,7 @@ export interface ComputeSubpassBuilder extends Setter { addTexture ( name: string, slotName: string, - sampler?: Sampler | null, + sampler?: Sampler, plane?: number): void; /** * @en Add storage buffer. @@ -1180,7 +1178,7 @@ export interface ComputePassBuilder extends Setter { addTexture ( name: string, slotName: string, - sampler?: Sampler | null, + sampler?: Sampler, plane?: number): void; /** * @en Add storage buffer. @@ -1394,7 +1392,7 @@ export interface Pipeline extends BasicPipeline { addBuiltinGpuCullingPass ( camera: Camera, hzbName?: string, - light?: Light | null): void; + light?: Light): void; addBuiltinHzbGenerationPass (sourceDepthStencilName: string, targetHzbName: string): void; /** * @experimental diff --git a/cocos/rendering/custom/private.ts b/cocos/rendering/custom/private.ts index 62e2393c627..e0f40bd8b42 100644 --- a/cocos/rendering/custom/private.ts +++ b/cocos/rendering/custom/private.ts @@ -64,7 +64,7 @@ export interface ProgramLibrary { phaseID: number, name: string, defines: MacroRecord, - key?: string | null): ProgramProxy | null; + key?: string): ProgramProxy | undefined; getBlockSizes (phaseID: number, programName: string): number[]; getHandleMap (phaseID: number, programName: string): Record; getProgramID (phaseID: number, programName: string): number; diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index a0f7522c2c8..c7e69cd7b8f 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -226,6 +226,10 @@ export class PersistentBuffer { constructor (buffer: Buffer | null = null) { this.buffer = buffer; } + reset (buffer: Buffer | null = null): void { + this.buffer = buffer; + this.fenceValue = 0; + } /*refcount*/ buffer: Buffer | null; fenceValue = 0; } @@ -246,6 +250,10 @@ export class PersistentTexture { constructor (texture: Texture | null = null) { this.texture = texture; } + reset (texture: Texture | null = null): void { + this.texture = texture; + this.fenceValue = 0; + } /*refcount*/ texture: Texture | null; fenceValue = 0; } @@ -747,14 +755,12 @@ export interface ResourceGraphVisitor { export type ResourceGraphObject = ManagedResource | ManagedBuffer | ManagedTexture -| Buffer -| Texture +| PersistentBuffer +| PersistentTexture | Framebuffer | RenderSwapchain | FormatView -| SubresourceView -| PersistentBuffer -| PersistentTexture; +| SubresourceView; //----------------------------------------------------------------- // Graph Concept @@ -2514,7 +2520,9 @@ export class RenderGraphObjectPoolSettings { this.renderSwapchainBatchSize = batchSize; this.resourceStatesBatchSize = batchSize; this.managedBufferBatchSize = batchSize; + this.persistentBufferBatchSize = batchSize; this.managedTextureBatchSize = batchSize; + this.persistentTextureBatchSize = batchSize; this.managedResourceBatchSize = batchSize; this.subpassBatchSize = batchSize; this.subpassGraphBatchSize = batchSize; @@ -2546,7 +2554,9 @@ export class RenderGraphObjectPoolSettings { renderSwapchainBatchSize = 16; resourceStatesBatchSize = 16; managedBufferBatchSize = 16; + persistentBufferBatchSize = 16; managedTextureBatchSize = 16; + persistentTextureBatchSize = 16; managedResourceBatchSize = 16; subpassBatchSize = 16; subpassGraphBatchSize = 16; @@ -2582,7 +2592,9 @@ export class RenderGraphObjectPool { this._renderSwapchain = new RecyclePool(() => new RenderSwapchain(), settings.renderSwapchainBatchSize); this._resourceStates = new RecyclePool(() => new ResourceStates(), settings.resourceStatesBatchSize); this._managedBuffer = new RecyclePool(() => new ManagedBuffer(), settings.managedBufferBatchSize); + this._persistentBuffer = new RecyclePool(() => new PersistentBuffer(), settings.persistentBufferBatchSize); this._managedTexture = new RecyclePool(() => new ManagedTexture(), settings.managedTextureBatchSize); + this._persistentTexture = new RecyclePool(() => new PersistentTexture(), settings.persistentTextureBatchSize); this._managedResource = new RecyclePool(() => new ManagedResource(), settings.managedResourceBatchSize); this._subpass = new RecyclePool(() => new Subpass(), settings.subpassBatchSize); this._subpassGraph = new RecyclePool(() => new SubpassGraph(), settings.subpassGraphBatchSize); @@ -2615,7 +2627,9 @@ export class RenderGraphObjectPool { this._renderSwapchain.reset(); this._resourceStates.reset(); this._managedBuffer.reset(); + this._persistentBuffer.reset(); this._managedTexture.reset(); + this._persistentTexture.reset(); this._managedResource.reset(); this._subpass.reset(); this._subpassGraph.reset(); @@ -2704,6 +2718,13 @@ export class RenderGraphObjectPool { v.reset(buffer); return v; } + createPersistentBuffer ( + buffer: Buffer | null = null, + ): PersistentBuffer { + const v = this._persistentBuffer.add(); + v.reset(buffer); + return v; + } createManagedTexture ( texture: Texture | null = null, ): ManagedTexture { @@ -2711,6 +2732,13 @@ export class RenderGraphObjectPool { v.reset(texture); return v; } + createPersistentTexture ( + texture: Texture | null = null, + ): PersistentTexture { + const v = this._persistentTexture.add(); + v.reset(texture); + return v; + } createManagedResource (): ManagedResource { const v = this._managedResource.add(); v.reset(); @@ -2861,7 +2889,9 @@ export class RenderGraphObjectPool { private readonly _renderSwapchain: RecyclePool; private readonly _resourceStates: RecyclePool; private readonly _managedBuffer: RecyclePool; + private readonly _persistentBuffer: RecyclePool; private readonly _managedTexture: RecyclePool; + private readonly _persistentTexture: RecyclePool; private readonly _managedResource: RecyclePool; private readonly _subpass: RecyclePool; private readonly _subpassGraph: RecyclePool; diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 47ff74a394c..577955e8017 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -210,6 +210,7 @@ export enum SceneFlags { DRAW_NON_INSTANCING = 0x1000, REFLECTION_PROBE = 0x2000, GPU_DRIVEN = 0x4000, + NON_BUILTIN = 0x8000, ALL = 0xFFFFFFFF, } diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 133f40ca697..f1fe7cb129c 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -29,7 +29,7 @@ import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency, UploadPair } from './types'; import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass, PersistentBuffer } from './render-graph'; -import { ComputePassBuilder, ComputeQueueBuilder, BasicPipeline, PipelineBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder, Setter } from './pipeline'; +import { ComputePassBuilder, ComputeQueueBuilder, BasicPipeline, PipelineBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder, Setter, SceneBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight, ProbeType } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; @@ -275,10 +275,10 @@ export class WebSetter implements Setter { public setBuiltinShadowMapConstants (light: Light, numLevels?: number): void { // TODO } - public setBuiltinDirectionalLightViewConstants (camera: Camera, light: DirectionalLight, level = 0): void { - setShadowUBOLightView(this, camera, light, level); + public setBuiltinDirectionalLightFrustumConstants (camera: Camera, light: DirectionalLight, csmLevel = 0): void { + setShadowUBOLightView(this, camera, light, csmLevel); } - public setBuiltinSpotLightViewConstants (light: SpotLight): void { + public setBuiltinSpotLightFrustumConstants (light: SpotLight): void { // TODO } public setBuiltinDirectionalLightConstants (light: DirectionalLight, camera: Camera): void { @@ -327,7 +327,7 @@ function setShadowUBOLightView ( setter: WebSetter, camera: Camera, light: Light, - level: number, + csmLevel: number, layout = 'default', ): void { const director = cclegacy.director; @@ -383,7 +383,7 @@ function setShadowUBOLightView ( setter.offsetVec4(_uboVec, uniformOffset); } } else { - const layer = csmLayers.layers[level]; + const layer = csmLayers.layers[csmLevel]; matShadowView = layer.matShadowView; matShadowProj = layer.matShadowProj; matShadowViewProj = layer.matShadowViewProj; @@ -879,6 +879,39 @@ function getResourceDimension (type: TextureType): ResourceDimension { return ResourceDimension.TEXTURE2D; } +export class WebSceneBuilder extends WebSetter implements SceneBuilder { + constructor ( + data: RenderData, + layoutGraph: LayoutGraphData, + rg: RenderGraph, + sceneId: number, + scene: SceneData, + ) { + super(data, layoutGraph); + this._renderGraph = rg; + this._scene = scene; + this._sceneId = sceneId; + } + useLightFrustum (light: Light, csmLevel = 0, optCamera: Camera | undefined = undefined): void { + this._scene.light.light = light; + this._scene.light.level = csmLevel; + this._scene.light.culledByLight = true; + if (optCamera) { + this._scene.camera = optCamera; + } + if (this._scene.flags & SceneFlags.NON_BUILTIN) { + return; + } + const queueId = this._renderGraph.getParent(this._sceneId); + const passId = this._renderGraph.getParent(queueId); + const layoutName = this._renderGraph.getLayout(passId); + setShadowUBOLightView(this, this._scene.camera!, light, csmLevel, layoutName); + } + private readonly _renderGraph: RenderGraph; + private readonly _scene: SceneData; + private readonly _sceneId: number; +} + export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuilder { constructor (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, vertID: number, queue: RenderQueue, pipeline: PipelineSceneData) { super(data, layoutGraph); @@ -923,23 +956,27 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild setTextureUBOView(this, camera, this._pipeline); initGlobalDescBinding(this._data, layoutName); } - addScene (camera: Camera, sceneFlags = SceneFlags.NONE): Setter { + addScene (camera: Camera, sceneFlags = SceneFlags.NONE, light: Light | undefined = undefined): SceneBuilder { const sceneData = new SceneData(camera.scene, camera, sceneFlags); + if (light) { + sceneData.light.light = light; + } const renderData = new RenderData(); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); - return new WebSetter(renderData, this._lg); - } - addSceneCulledByDirectionalLight (camera: Camera, sceneFlags: SceneFlags, light: DirectionalLight, level: number): Setter { - const sceneData = new SceneData(camera.scene, camera, sceneFlags, new LightInfo(light, level)); - const renderData = new RenderData(); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); - return new WebSetter(renderData, this._lg); - } - addSceneCulledBySpotLight (camera: Camera, sceneFlags: SceneFlags, light: SpotLight): Setter { - const sceneData = new SceneData(camera.scene, camera, sceneFlags, new LightInfo(light, 0)); - const renderData = new RenderData(); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); - return new WebSetter(renderData, this._lg); + const sceneId = this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); + if (!(sceneFlags & SceneFlags.NON_BUILTIN)) { + const layoutName = this.getLayoutName(); + setCameraUBOValues( + this, + camera, + this._pipeline, + camera.scene, + layoutName, + ); + setShadowUBOView(this, camera, layoutName); + setTextureUBOView(this, camera, this._pipeline); + initGlobalDescBinding(this._data, layoutName); + } + return new WebSceneBuilder(renderData, this._lg, this._renderGraph, sceneId, sceneData); } addFullscreenQuad (material: Material, passID: number, sceneFlags = SceneFlags.NONE, name = 'Quad'): void { this._renderGraph.addVertex( @@ -1838,13 +1875,15 @@ export class WebPipeline implements BasicPipeline { public get constantMacros (): string { return this._constantMacros; } - public get profiler (): Model | null { - return this._profiler; + public get profiler (): Model | undefined { + return this._profiler ? this._profiler : undefined; } - public set profiler (profiler: Model | null) { - this._profiler = profiler; + public set profiler (profiler: Model | undefined) { + if (profiler) { + this._profiler = profiler; + } } - public get geometryRenderer (): GeometryRenderer | null { + public get geometryRenderer (): GeometryRenderer | undefined { throw new Error('Method not implemented.'); } public get shadingScale (): number { diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 4ead5bdd8cc..f224a739172 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -314,12 +314,12 @@ RenderingInfo FrameGraphDispatcher::getRenderPassAndFrameBuffer(RenderGraph::ver CC_EXPECTS(tex.texture); fbInfo.colorTextures.emplace_back(tex.texture); }, - [&](const IntrusivePtr &res) { + [&](const PersistentBuffer &res) { std::ignore = res; CC_EXPECTS(false); }, - [&](const IntrusivePtr &tex) { - fbInfo.colorTextures.emplace_back(tex); + [&](const PersistentTexture &tex) { + fbInfo.colorTextures.emplace_back(tex.texture); }, [&](const IntrusivePtr &fb) { CC_EXPECTS(fb->getColorTextures().size() == 1); diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 1860969b097..29fc3204c2d 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -57,7 +57,7 @@ namespace render { class NativeRenderNode; class NativeSetter; -class NativeSetterBuilder; +class NativeSceneBuilder; class NativeRenderSubpassBuilderImpl; class NativeRenderQueueBuilder; class NativeRenderSubpassBuilder; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index cfe8ccd47fe..06216cc2e83 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -96,8 +96,8 @@ class NativeSetter : public NativeRenderNode { void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) /*implements*/; void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) /*implements*/; void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) /*implements*/; - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) /*implements*/; - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) /*implements*/; + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) /*implements*/; + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) /*implements*/; void setVec4ArraySize(const ccstd::string& name, uint32_t sz); void setVec4ArrayElem(const ccstd::string& name, const cc::Vec4& vec, uint32_t id); @@ -109,9 +109,9 @@ class NativeSetter : public NativeRenderNode { uint32_t layoutID{LayoutGraphData::null_vertex()}; }; -class NativeSetterBuilder final : public Setter, public NativeSetter { +class NativeSceneBuilder final : public SceneBuilder, public NativeSetter { public: - NativeSetterBuilder(const PipelineRuntime* pipelineRuntimeIn, RenderGraph* renderGraphIn, uint32_t nodeIDIn, const LayoutGraphData* layoutGraphIn, uint32_t layoutIDIn) noexcept + NativeSceneBuilder(const PipelineRuntime* pipelineRuntimeIn, RenderGraph* renderGraphIn, uint32_t nodeIDIn, const LayoutGraphData* layoutGraphIn, uint32_t layoutIDIn) noexcept : NativeSetter(pipelineRuntimeIn, renderGraphIn, nodeIDIn, layoutGraphIn, layoutIDIn) {} ccstd::string getName() const override { @@ -181,12 +181,14 @@ class NativeSetterBuilder final : public Setter, public NativeSetter { void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } + + void useLightFrustum(IntrusivePtr light, uint32_t csmLevel, const scene::Camera *optCamera) override; }; class NativeRenderSubpassBuilderImpl : public NativeSetter { @@ -278,17 +280,15 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) override; - Setter *addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) override; - Setter *addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) override; - Setter *addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) override; + SceneBuilder *addScene(const scene::Camera *camera, SceneFlags sceneFlags, scene::Light *light) 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; @@ -368,11 +368,11 @@ class NativeRenderSubpassBuilder final : public RenderSubpassBuilder, public Nat void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addRenderTarget(const ccstd::string &name, AccessType accessType, const ccstd::string &slotName, gfx::LoadOp loadOp, gfx::StoreOp storeOp, const gfx::Color &color) override { @@ -479,11 +479,11 @@ class NativeMultisampleRenderSubpassBuilder final : public MultisampleRenderSubp void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addRenderTarget(const ccstd::string &name, AccessType accessType, const ccstd::string &slotName, gfx::LoadOp loadOp, gfx::StoreOp storeOp, const gfx::Color &color) override { @@ -593,11 +593,11 @@ class NativeComputeSubpassBuilder final : public ComputeSubpassBuilder, public N void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addRenderTarget(const ccstd::string &name, const ccstd::string &slotName) override; @@ -680,11 +680,11 @@ class NativeRenderPassBuilder final : public RenderPassBuilder, public NativeSet void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addRenderTarget(const ccstd::string &name, gfx::LoadOp loadOp, gfx::StoreOp storeOp, const gfx::Color &color) override; @@ -779,11 +779,11 @@ class NativeMultisampleRenderPassBuilder final : public MultisampleRenderPassBui void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addRenderTarget(const ccstd::string &name, gfx::LoadOp loadOp, gfx::StoreOp storeOp, const gfx::Color &color) override; @@ -877,11 +877,11 @@ class NativeComputeQueueBuilder final : public ComputeQueueBuilder, public Nativ void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addDispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, Material *material, uint32_t passID) override; @@ -959,11 +959,11 @@ class NativeComputePassBuilder final : public ComputePassBuilder, public NativeS void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); } - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) override { - NativeSetter::setBuiltinDirectionalLightViewConstants(camera, light, level); + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) override { + NativeSetter::setBuiltinDirectionalLightFrustumConstants(camera, light, csmLevel); } - void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) override { - NativeSetter::setBuiltinSpotLightViewConstants(light); + void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) override { + NativeSetter::setBuiltinSpotLightFrustumConstants(light); } void addTexture(const ccstd::string &name, const ccstd::string &slotName, gfx::Sampler *sampler, uint32_t plane) override; diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 8974aaa4255..0b028506e07 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -759,23 +759,75 @@ void NativeRenderQueueBuilder::addSceneOfCamera( data); } -Setter *NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { - auto cullingFlags = CullingFlags::CAMERA_FRUSTUM; - if (light) { - cullingFlags |= CullingFlags::LIGHT_BOUNDS; +void NativeSceneBuilder::useLightFrustum( + IntrusivePtr light, uint32_t csmLevel, const scene::Camera *optCamera) { + auto &sceneData = get(SceneTag{}, nodeID, *renderGraph); + sceneData.light.light = light; + sceneData.light.level = csmLevel; + sceneData.light.culledByLight = true; + if (optCamera) { + sceneData.camera = optCamera; + } + if (any(sceneData.flags & SceneFlags::NON_BUILTIN)) { + return; } - SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{}, cullingFlags); - auto sceneID = addVertex2( + const auto *pLight = dynamic_cast(light.get()); + if (pLight) { + setBuiltinDirectionalLightFrustumConstants(sceneData.camera, pLight, csmLevel); + } else { + CC_EXPECTS(false); + } +} + +SceneBuilder *NativeRenderQueueBuilder::addScene( + const scene::Camera *camera, SceneFlags sceneFlags, scene::Light *light) { + 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(std::move(data)), + std::forward_as_tuple( + camera->getScene(), // Scene and camera should be decoupled. + camera, // They are coupled for now. + sceneFlags, + LightInfo{light, 0}, // When doing rendering, csmLevel is irrelevant, set to zero. + // Objects are projected to camera by default and are culled further if light is available. + light ? CullingFlags::CAMERA_FRUSTUM | CullingFlags::LIGHT_BOUNDS + : CullingFlags::CAMERA_FRUSTUM), *renderGraph, nodeID); CC_ENSURES(sceneID != RenderGraph::null_vertex()); + auto builder = std::make_unique( + pipelineRuntime, + renderGraph, + sceneID, + layoutGraph, + layoutID); + + if (!any(sceneFlags & SceneFlags::NON_BUILTIN)) { + // objects are projected to camera, set camera ubo + builder->setBuiltinCameraConstants(camera); + + if (const auto *pDirLight = camera->getScene()->getMainLight(); pDirLight) { + // light is directional + builder->setBuiltinDirectionalLightConstants(pDirLight, camera); + } else if (light) { + // light is non-directional + // builder->setBuiltinXxxLightConstants(light, camera); + CC_EXPECTS(false); + } + + // set builtin legacy ubo + auto &data = get(RenderGraph::DataTag{}, *renderGraph, sceneID); + setLegacyTextureUBOView( + *pipelineRuntime->getDevice(), + *layoutGraph, + *pipelineRuntime->getPipelineSceneData(), + data); + } + if (any(sceneFlags & SceneFlags::GPU_DRIVEN)) { const auto passID = renderGraph->getPassID(nodeID); const auto cullingID = dynamic_cast(pipelineRuntime)->nativeContext.sceneCulling.gpuCullingPassID; @@ -812,62 +864,7 @@ Setter *NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFla } } - return new NativeSetterBuilder( - pipelineRuntime, - renderGraph, - sceneID, - layoutGraph, - layoutID); -} - -Setter *NativeRenderQueueBuilder::addSceneCulledByDirectionalLight( - const scene::Camera *camera, SceneFlags sceneFlags, - scene::DirectionalLight *light, uint32_t level) { - CC_EXPECTS(light); - CC_EXPECTS(light->getType() != scene::LightType::UNKNOWN); - SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{light, level}, CullingFlags::LIGHT_FRUSTUM); - - 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(std::move(data)), - *renderGraph, nodeID); - CC_ENSURES(sceneID != RenderGraph::null_vertex()); - - return new NativeSetterBuilder( - pipelineRuntime, - renderGraph, - sceneID, - layoutGraph, - layoutID); -} - -Setter *NativeRenderQueueBuilder::addSceneCulledBySpotLight( - const scene::Camera *camera, SceneFlags sceneFlags, - scene::SpotLight *light) { - CC_EXPECTS(light); - CC_EXPECTS(light->getType() != scene::LightType::UNKNOWN); - SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{light, 0}, CullingFlags::LIGHT_FRUSTUM); - - 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(std::move(data)), - *renderGraph, nodeID); - CC_ENSURES(sceneID != RenderGraph::null_vertex()); - - return new NativeSetterBuilder( - pipelineRuntime, - renderGraph, - sceneID, - layoutGraph, - layoutID); + return builder.release(); } void NativeRenderQueueBuilder::addFullscreenQuad( diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 604a9aca1fa..736283688ab 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -207,12 +207,12 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_ENSURES(texture.texture); texture.fenceValue = nextFenceValue; }, - [&](const IntrusivePtr& buffer) { - CC_EXPECTS(buffer); + [&](const PersistentBuffer& buffer) { + CC_EXPECTS(buffer.buffer); std::ignore = buffer; }, - [&](const IntrusivePtr& texture) { - CC_EXPECTS(texture); + [&](const PersistentTexture& texture) { + CC_EXPECTS(texture.texture); std::ignore = texture; }, [&](const IntrusivePtr& fb) { diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index 0ff02f007b7..b06cfbbc52b 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -123,7 +123,7 @@ void NativeSetter::setBuiltinCameraConstants(const scene::Camera *camera) { camera->getScene()->getMainLight(), data); } -void NativeSetter::setBuiltinDirectionalLightViewConstants( +void NativeSetter::setBuiltinDirectionalLightFrustumConstants( const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) { CC_EXPECTS(light); @@ -138,7 +138,7 @@ void NativeSetter::setBuiltinDirectionalLightViewConstants( setShadowUBOLightView(device, *layoutGraph, sceneData, csm, *light, level, data); } -void NativeSetter::setBuiltinSpotLightViewConstants(const scene::SpotLight *light) { +void NativeSetter::setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) { CC_EXPECTS(light); auto *device = pipelineRuntime->getDevice(); const auto &sceneData = *pipelineRuntime->getPipelineSceneData(); diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index 2054c2d314e..8a60f7aa6c1 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -168,6 +168,7 @@ enum class SceneFlags : uint32_t { DRAW_NON_INSTANCING = 0x1000, REFLECTION_PROBE = 0x2000, GPU_DRIVEN = 0x4000, + NON_BUILTIN = 0x8000, ALL = 0xFFFFFFFF, }; diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h b/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h index 09e8106431a..9714e8db649 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphFwd.h @@ -45,7 +45,9 @@ struct ResourceTraits; struct RenderSwapchain; struct ResourceStates; struct ManagedBuffer; +struct PersistentBuffer; struct ManagedTexture; +struct PersistentTexture; struct ManagedResource; struct Subpass; struct SubpassGraph; diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphGraphs.h b/native/cocos/renderer/pipeline/custom/RenderGraphGraphs.h index e14bfd7c411..9f129ec00ea 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphGraphs.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphGraphs.h @@ -1523,7 +1523,7 @@ holds_alternative(ResourceGraph::vertex_descriptor v, const Reso template <> inline bool -holds_alternative>(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) noexcept { // NOLINT +holds_alternative(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) noexcept { // NOLINT return ccstd::holds_alternative< impl::ValueHandle>( g._vertices[v].handle); @@ -1531,7 +1531,7 @@ holds_alternative>(ResourceGraph::vertex_descriptor v, template <> inline bool -holds_alternative>(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) noexcept { // NOLINT +holds_alternative(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) noexcept { // NOLINT return ccstd::holds_alternative< impl::ValueHandle>( g._vertices[v].handle); @@ -1601,8 +1601,8 @@ get(ResourceGraph::vertex_descriptor v, ResourceGraph& g) { } template <> -inline IntrusivePtr& -get>(ResourceGraph::vertex_descriptor v, ResourceGraph& g) { +inline PersistentBuffer& +get(ResourceGraph::vertex_descriptor v, ResourceGraph& g) { auto& handle = ccstd::get< impl::ValueHandle>( g._vertices[v].handle); @@ -1610,8 +1610,8 @@ get>(ResourceGraph::vertex_descriptor v, ResourceGraph } template <> -inline IntrusivePtr& -get>(ResourceGraph::vertex_descriptor v, ResourceGraph& g) { +inline PersistentTexture& +get(ResourceGraph::vertex_descriptor v, ResourceGraph& g) { auto& handle = ccstd::get< impl::ValueHandle>( g._vertices[v].handle); @@ -1686,8 +1686,8 @@ get(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) } template <> -inline const IntrusivePtr& -get>(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) { +inline const PersistentBuffer& +get(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) { const auto& handle = ccstd::get< impl::ValueHandle>( g._vertices[v].handle); @@ -1695,8 +1695,8 @@ get>(ResourceGraph::vertex_descriptor v, const Resourc } template <> -inline const IntrusivePtr& -get>(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) { +inline const PersistentTexture& +get(ResourceGraph::vertex_descriptor v, const ResourceGraph& g) { const auto& handle = ccstd::get< impl::ValueHandle>( g._vertices[v].handle); @@ -1763,7 +1763,7 @@ get(ManagedTextureTag /*tag*/, ResourceGraph::vertex_descriptor v, ResourceGraph return g.managedTextures[handle.value]; } -inline IntrusivePtr& +inline PersistentBuffer& get(PersistentBufferTag /*tag*/, ResourceGraph::vertex_descriptor v, ResourceGraph& g) { auto& handle = ccstd::get< impl::ValueHandle>( @@ -1771,7 +1771,7 @@ get(PersistentBufferTag /*tag*/, ResourceGraph::vertex_descriptor v, ResourceGra return g.buffers[handle.value]; } -inline IntrusivePtr& +inline PersistentTexture& get(PersistentTextureTag /*tag*/, ResourceGraph::vertex_descriptor v, ResourceGraph& g) { auto& handle = ccstd::get< impl::ValueHandle>( @@ -1835,7 +1835,7 @@ get(ManagedTextureTag /*tag*/, ResourceGraph::vertex_descriptor v, const Resourc return g.managedTextures[handle.value]; } -inline const IntrusivePtr& +inline const PersistentBuffer& get(PersistentBufferTag /*tag*/, ResourceGraph::vertex_descriptor v, const ResourceGraph& g) { const auto& handle = ccstd::get< impl::ValueHandle>( @@ -1843,7 +1843,7 @@ get(PersistentBufferTag /*tag*/, ResourceGraph::vertex_descriptor v, const Resou return g.buffers[handle.value]; } -inline const IntrusivePtr& +inline const PersistentTexture& get(PersistentTextureTag /*tag*/, ResourceGraph::vertex_descriptor v, const ResourceGraph& g) { const auto& handle = ccstd::get< impl::ValueHandle>( @@ -1939,9 +1939,9 @@ get_if(ResourceGraph::vertex_descriptor v, ResourceGraph* pGraph } template <> -inline IntrusivePtr* -get_if>(ResourceGraph::vertex_descriptor v, ResourceGraph* pGraph) noexcept { // NOLINT - IntrusivePtr* ptr = nullptr; +inline PersistentBuffer* +get_if(ResourceGraph::vertex_descriptor v, ResourceGraph* pGraph) noexcept { // NOLINT + PersistentBuffer* ptr = nullptr; if (!pGraph) { return ptr; } @@ -1956,9 +1956,9 @@ get_if>(ResourceGraph::vertex_descriptor v, ResourceGr } template <> -inline IntrusivePtr* -get_if>(ResourceGraph::vertex_descriptor v, ResourceGraph* pGraph) noexcept { // NOLINT - IntrusivePtr* ptr = nullptr; +inline PersistentTexture* +get_if(ResourceGraph::vertex_descriptor v, ResourceGraph* pGraph) noexcept { // NOLINT + PersistentTexture* ptr = nullptr; if (!pGraph) { return ptr; } @@ -2096,9 +2096,9 @@ get_if(ResourceGraph::vertex_descriptor v, const ResourceGraph* } template <> -inline const IntrusivePtr* -get_if>(ResourceGraph::vertex_descriptor v, const ResourceGraph* pGraph) noexcept { // NOLINT - const IntrusivePtr* ptr = nullptr; +inline const PersistentBuffer* +get_if(ResourceGraph::vertex_descriptor v, const ResourceGraph* pGraph) noexcept { // NOLINT + const PersistentBuffer* ptr = nullptr; if (!pGraph) { return ptr; } @@ -2113,9 +2113,9 @@ get_if>(ResourceGraph::vertex_descriptor v, const Reso } template <> -inline const IntrusivePtr* -get_if>(ResourceGraph::vertex_descriptor v, const ResourceGraph* pGraph) noexcept { // NOLINT - const IntrusivePtr* ptr = nullptr; +inline const PersistentTexture* +get_if(ResourceGraph::vertex_descriptor v, const ResourceGraph* pGraph) noexcept { // NOLINT + const PersistentTexture* ptr = nullptr; if (!pGraph) { return ptr; } @@ -2432,7 +2432,7 @@ void addVertexImpl( // NOLINT template void addVertexImpl( // NOLINT ValueT &&val, ResourceGraph &g, ResourceGraph::Vertex &vert, // NOLINT - std::enable_if_t, IntrusivePtr>::value>* dummy = nullptr) { // NOLINT + std::enable_if_t, PersistentBuffer>::value>* dummy = nullptr) { // NOLINT vert.handle = impl::ValueHandle{ gsl::narrow_cast(g.buffers.size())}; g.buffers.emplace_back(std::forward(val)); @@ -2441,7 +2441,7 @@ void addVertexImpl( // NOLINT template void addVertexImpl( // NOLINT ValueT &&val, ResourceGraph &g, ResourceGraph::Vertex &vert, // NOLINT - std::enable_if_t, IntrusivePtr>::value>* dummy = nullptr) { // NOLINT + std::enable_if_t, PersistentTexture>::value>* dummy = nullptr) { // NOLINT vert.handle = impl::ValueHandle{ gsl::narrow_cast(g.textures.size())}; g.textures.emplace_back(std::forward(val)); diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h index 2a6db6b7445..16efc9103a2 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h @@ -211,6 +211,15 @@ struct ManagedBuffer { uint64_t fenceValue{0}; }; +struct PersistentBuffer { + PersistentBuffer() = default; + PersistentBuffer(IntrusivePtr bufferIn) noexcept // NOLINT + : buffer(std::move(bufferIn)) {} + + IntrusivePtr buffer; + uint64_t fenceValue{0}; +}; + struct ManagedTexture { ManagedTexture() = default; ManagedTexture(IntrusivePtr textureIn) noexcept // NOLINT @@ -222,6 +231,17 @@ struct ManagedTexture { uint64_t fenceValue{0}; }; +struct PersistentTexture { + PersistentTexture() = default; + PersistentTexture(IntrusivePtr textureIn) noexcept // NOLINT + : texture(std::move(textureIn)) {} + + bool checkResource(const ResourceDesc &desc) const; + + IntrusivePtr texture; + uint64_t fenceValue{0}; +}; + struct ManagedResource { uint32_t unused{0}; }; @@ -638,8 +658,8 @@ struct ResourceGraph { // PolymorphicGraph using VertexTag = ccstd::variant; - using VertexValue = ccstd::variant*, IntrusivePtr*, IntrusivePtr*, RenderSwapchain*, FormatView*, SubresourceView*>; - using VertexConstValue = ccstd::variant*, const IntrusivePtr*, const IntrusivePtr*, const RenderSwapchain*, const FormatView*, const SubresourceView*>; + using VertexValue = ccstd::variant*, RenderSwapchain*, FormatView*, SubresourceView*>; + using VertexConstValue = ccstd::variant*, const RenderSwapchain*, const FormatView*, const SubresourceView*>; using VertexHandle = ccstd::variant< impl::ValueHandle, impl::ValueHandle, @@ -702,8 +722,8 @@ struct ResourceGraph { ccstd::pmr::vector resources; ccstd::pmr::vector managedBuffers; ccstd::pmr::vector managedTextures; - ccstd::pmr::vector> buffers; - ccstd::pmr::vector> textures; + ccstd::pmr::vector buffers; + ccstd::pmr::vector textures; ccstd::pmr::vector> framebuffers; ccstd::pmr::vector swapchains; ccstd::pmr::vector formatViews; diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h index ee0505f07f2..8a6545cc0e1 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceFwd.h @@ -44,6 +44,7 @@ enum class SubpassCapabilities : uint32_t; struct PipelineCapabilities; class RenderNode; class Setter; +class SceneBuilder; class RenderQueueBuilder; class BasicRenderPassBuilder; class BasicMultisampleRenderPassBuilder; diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 3e2078df625..3756b7c9672 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -460,10 +460,23 @@ class Setter : public RenderNode { virtual void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) = 0; virtual void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) = 0; virtual void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) = 0; - virtual void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t level) = 0; - virtual void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) = 0; - void setBuiltinDirectionalLightViewConstants(const scene::Camera *camera, const scene::DirectionalLight *light) { - setBuiltinDirectionalLightViewConstants(camera, light, 0); + virtual void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light, uint32_t csmLevel) = 0; + virtual void setBuiltinSpotLightFrustumConstants(const scene::SpotLight *light) = 0; + void setBuiltinDirectionalLightFrustumConstants(const scene::Camera *camera, const scene::DirectionalLight *light) { + setBuiltinDirectionalLightFrustumConstants(camera, light, 0); + } +}; + +class SceneBuilder : public Setter { +public: + SceneBuilder() noexcept = default; + + virtual void useLightFrustum(IntrusivePtr light, uint32_t csmLevel, const scene::Camera *optCamera) = 0; + void useLightFrustum(IntrusivePtr light) { + useLightFrustum(std::move(light), 0, nullptr); + } + void useLightFrustum(IntrusivePtr light, uint32_t csmLevel) { + useLightFrustum(std::move(light), csmLevel, nullptr); } }; @@ -488,9 +501,7 @@ class RenderQueueBuilder : public Setter { * @param sceneFlags @en Rendering flags of the scene @zh 场景渲染标志位 */ virtual void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) = 0; - virtual Setter *addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) = 0; - virtual Setter *addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) = 0; - virtual Setter *addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) = 0; + virtual SceneBuilder *addScene(const scene::Camera *camera, SceneFlags sceneFlags, scene::Light *light) = 0; /** * @en Render a full-screen quad. * @zh 渲染全屏四边形 @@ -528,7 +539,7 @@ class RenderQueueBuilder : public Setter { void addSceneOfCamera(scene::Camera *camera, LightInfo light) { addSceneOfCamera(camera, std::move(light), SceneFlags::NONE); } - Setter *addScene(const scene::Camera *camera, SceneFlags sceneFlags) { + SceneBuilder *addScene(const scene::Camera *camera, SceneFlags sceneFlags) { return addScene(camera, sceneFlags, nullptr); } void addFullscreenQuad(Material *material, uint32_t passID) { diff --git a/native/tools/swig-config/render.i b/native/tools/swig-config/render.i index 044b59f10e7..877b83049fe 100644 --- a/native/tools/swig-config/render.i +++ b/native/tools/swig-config/render.i @@ -82,8 +82,6 @@ using namespace cc::render; %release_returned_cpp_object_in_gc(cc::render::RenderPassBuilder::addComputeSubpass); %release_returned_cpp_object_in_gc(cc::render::ComputePassBuilder::addQueue); %release_returned_cpp_object_in_gc(cc::render::RenderQueueBuilder::addScene); -%release_returned_cpp_object_in_gc(cc::render::RenderQueueBuilder::addSceneCulledByDirectionalLight); -%release_returned_cpp_object_in_gc(cc::render::RenderQueueBuilder::addSceneCulledBySpotLight); %release_returned_cpp_object_in_gc(cc::render::Pipeline::addRenderPass); %release_returned_cpp_object_in_gc(cc::render::Pipeline::addComputePass); diff --git a/package-lock.json b/package-lock.json index e1185a3f10c..a892eef22fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cocos-creator", - "version": "3.8.1", + "version": "3.8.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cocos-creator", - "version": "3.8.1", + "version": "3.8.2", "hasInstallScript": true, "license": "MIT", "dependencies": { From 755937957d3f2ee34133313ad38b3aaed3381896 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 12 Sep 2023 11:48:56 +0800 Subject: [PATCH 59/82] onGlobalPipelineStateChanged added --- cocos/rendering/custom/pipeline.ts | 1 + native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h | 1 + 2 files changed, 2 insertions(+) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index c749445f4f7..b8b1ea207d2 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -1426,6 +1426,7 @@ export interface PipelineBuilder { * @param pipeline @en Current render pipeline @zh 当前管线 */ setup (cameras: Camera[], pipeline: BasicPipeline): void; + onGlobalPipelineStateChanged? (): void; } /** diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 3756b7c9672..bec2b17666e 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -1509,6 +1509,7 @@ class PipelineBuilder { * @param pipeline @en Current render pipeline @zh 当前管线 */ virtual void setup(const ccstd::vector &cameras, BasicPipeline *pipeline) = 0; + virtual void onGlobalPipelineStateChanged() = 0; }; /** From 36a8efbc4174cd8a156cfbf9cedb590c8c2cf946 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 12 Sep 2023 15:34:15 +0800 Subject: [PATCH 60/82] revert optional to null --- cocos/rendering/custom/pipeline.ts | 4 ++-- cocos/rendering/custom/private.ts | 2 +- cocos/rendering/custom/render-graph.ts | 9 ++++++++- cocos/rendering/custom/web-pipeline.ts | 12 +++++------- cocos/rendering/post-process/passes/base-pass.ts | 4 ++-- .../renderer/pipeline/custom/NativeExecutor.cpp | 3 +++ .../renderer/pipeline/custom/NativeRenderGraph.cpp | 14 +++++++++++--- .../pipeline/custom/NativeSceneCulling.cpp | 4 ++-- .../renderer/pipeline/custom/RenderCommonTypes.h | 12 ++++++++++++ .../renderer/pipeline/custom/RenderGraphTypes.h | 10 ++++++++-- .../pipeline/custom/RenderInterfaceTypes.h | 4 ++++ 11 files changed, 58 insertions(+), 20 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index b8b1ea207d2..4005d5eac9d 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -119,13 +119,13 @@ export interface PipelineRuntime { * This model is used to render profile information in Debug mode. * @zh 获得分析工具(Profiler)的渲染实例,用于Debug模式下显示调试与性能检测信息 */ - profiler: Model | undefined; + profiler: Model | null; /** * @en Get geometry renderer. * Geometry renderer is used to render procedural geometries. * @zh 获得几何渲染器(GeometryRenderer),几何渲染器用于程序化渲染基础几何图形 */ - readonly geometryRenderer: GeometryRenderer | undefined; + readonly geometryRenderer: GeometryRenderer | null; /** * @en Get shading scale. * Shading scale affects shading texels per pixel. diff --git a/cocos/rendering/custom/private.ts b/cocos/rendering/custom/private.ts index e0f40bd8b42..b4cae1f5d17 100644 --- a/cocos/rendering/custom/private.ts +++ b/cocos/rendering/custom/private.ts @@ -64,7 +64,7 @@ export interface ProgramLibrary { phaseID: number, name: string, defines: MacroRecord, - key?: string): ProgramProxy | undefined; + key?: string): ProgramProxy | null; getBlockSizes (phaseID: number, programName: string): number[]; getHandleMap (phaseID: number, programName: string): Record; getProgramID (phaseID: number, programName: string): number; diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index c7e69cd7b8f..135d22cd640 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -35,6 +35,7 @@ import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp import { AccessType, AttachmentType, ClearValueType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UploadPair, RenderCommonObjectPool } from './types'; import { RenderScene } from '../../render-scene/core/render-scene'; import { RenderWindow } from '../../render-scene/core/render-window'; +import { Light } from '../../render-scene/scene'; import { RecyclePool } from '../../core/memop'; export class ClearValue { @@ -1532,30 +1533,35 @@ export class SceneData { flags: SceneFlags = SceneFlags.NONE, light: LightInfo = new LightInfo(), cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, + shadingLight: Light | null = null, ) { this.scene = scene; this.camera = camera; this.light = light; this.flags = flags; this.cullingFlags = cullingFlags; + this.shadingLight = shadingLight; } reset ( scene: RenderScene | null = null, camera: Camera | null = null, flags: SceneFlags = SceneFlags.NONE, cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, + shadingLight: Light | null = null, ): void { this.scene = scene; this.camera = camera; this.light.reset(); this.flags = flags; this.cullingFlags = cullingFlags; + this.shadingLight = shadingLight; } /*pointer*/ scene: RenderScene | null; /*pointer*/ camera: Camera | null; readonly light: LightInfo; flags: SceneFlags; cullingFlags: CullingFlags; + /*refcount*/ shadingLight: Light | null; } export class Dispatch { @@ -2844,9 +2850,10 @@ export class RenderGraphObjectPool { camera: Camera | null = null, flags: SceneFlags = SceneFlags.NONE, cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, + shadingLight: Light | null = null, ): SceneData { const v = this._sceneData.add(); - v.reset(scene, camera, flags, cullingFlags); + v.reset(scene, camera, flags, cullingFlags, shadingLight); return v; } createDispatch ( diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index f1fe7cb129c..ac65bfd8e2d 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -1875,15 +1875,13 @@ export class WebPipeline implements BasicPipeline { public get constantMacros (): string { return this._constantMacros; } - public get profiler (): Model | undefined { - return this._profiler ? this._profiler : undefined; + public get profiler (): Model | null { + return this._profiler; } - public set profiler (profiler: Model | undefined) { - if (profiler) { - this._profiler = profiler; - } + public set profiler (profiler: Model | null) { + this._profiler = profiler; } - public get geometryRenderer (): GeometryRenderer | undefined { + public get geometryRenderer (): GeometryRenderer | null { throw new Error('Method not implemented.'); } public get shadingScale (): number { diff --git a/cocos/rendering/post-process/passes/base-pass.ts b/cocos/rendering/post-process/passes/base-pass.ts index 54fecf11729..8260e67f517 100644 --- a/cocos/rendering/post-process/passes/base-pass.ts +++ b/cocos/rendering/post-process/passes/base-pass.ts @@ -41,14 +41,14 @@ export function disablePostProcessForDebugView (): boolean { return debugView.singleMode as number > 0; } -export function getShadowMapSampler (): Sampler | null { +export function getShadowMapSampler (): Sampler | undefined { if (!_pointSampler) { const director = cclegacy.director; const pipeline = director.root.pipeline; const device = pipeline.device; _pointSampler = device.getSampler(_samplerPointInfo); } - return _pointSampler; + return _pointSampler || undefined; } export abstract class BasePass { diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 7d77b7c2281..451942a2ff7 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -991,6 +991,9 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { updateAndCreatePerPassDescriptorSet(vertID); ctx.currentProjMatrix = sceneData.camera->getMatProj(); } + if (sceneData.shadingLight && !dynamic_cast(sceneData.shadingLight.get())) { + + } } else if (holds(vertID, ctx.g)) { const auto& blit = get(BlitTag{}, vertID, ctx.g); if (blit.camera) { diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 0b028506e07..f299e21eca5 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -710,7 +710,7 @@ CullingFlags makeCullingFlags(const LightInfo &light) { void NativeRenderQueueBuilder::addSceneOfCamera( scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) { const auto *pLight = light.light.get(); - SceneData scene(camera->getScene(), camera, sceneFlags, light, makeCullingFlags(light)); + SceneData scene(camera->getScene(), camera, sceneFlags, light, makeCullingFlags(light), light.light); auto sceneID = addVertex2( SceneTag{}, std::forward_as_tuple("Camera"), @@ -768,6 +768,13 @@ void NativeSceneBuilder::useLightFrustum( if (optCamera) { sceneData.camera = optCamera; } + + // Disable camera frustum projection + sceneData.cullingFlags &= ~CullingFlags::CAMERA_FRUSTUM; + + // Enable light frustum projection + sceneData.cullingFlags |= CullingFlags::LIGHT_FRUSTUM; + if (any(sceneData.flags & SceneFlags::NON_BUILTIN)) { return; } @@ -792,10 +799,11 @@ SceneBuilder *NativeRenderQueueBuilder::addScene( camera->getScene(), // Scene and camera should be decoupled. camera, // They are coupled for now. sceneFlags, - LightInfo{light, 0}, // When doing rendering, csmLevel is irrelevant, set to zero. + LightInfo{nullptr, 0}, // Objects are projected to camera by default and are culled further if light is available. light ? CullingFlags::CAMERA_FRUSTUM | CullingFlags::LIGHT_BOUNDS - : CullingFlags::CAMERA_FRUSTUM), + : CullingFlags::CAMERA_FRUSTUM, + light), *renderGraph, nodeID); CC_ENSURES(sceneID != RenderGraph::null_vertex()); diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 84018297d42..a9faffcf002 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -74,7 +74,7 @@ LightBoundsCullingID SceneCulling::getOrCreateLightBoundsCulling( return {}; } - CC_EXPECTS(sceneData.light.light); + CC_EXPECTS(sceneData.shadingLight); const auto* const scene = sceneData.scene; CC_EXPECTS(scene); @@ -86,7 +86,7 @@ LightBoundsCullingID SceneCulling::getOrCreateLightBoundsCulling( frustumCullingID, sceneData.camera, sceneData.light.probe, - sceneData.light.light, + sceneData.shadingLight, }; // find query source diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index 8a60f7aa6c1..873286c62f6 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -136,6 +136,10 @@ constexpr bool operator!(ResourceFlags e) noexcept { return e == static_cast(0); } +constexpr ResourceFlags operator~(ResourceFlags e) noexcept { + return static_cast(~static_cast>(e)); +} + constexpr bool any(ResourceFlags e) noexcept { return !!e; } @@ -192,6 +196,10 @@ constexpr bool operator!(SceneFlags e) noexcept { return e == static_cast(0); } +constexpr SceneFlags operator~(SceneFlags e) noexcept { + return static_cast(~static_cast>(e)); +} + constexpr bool any(SceneFlags e) noexcept { return !!e; } @@ -320,6 +328,10 @@ constexpr bool operator!(ResolveFlags e) noexcept { return e == static_cast(0); } +constexpr ResolveFlags operator~(ResolveFlags e) noexcept { + return static_cast(~static_cast>(e)); +} + constexpr bool any(ResolveFlags e) noexcept { return !!e; } diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h index 16efc9103a2..300a53b8c6b 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h @@ -895,24 +895,30 @@ constexpr bool operator!(CullingFlags e) noexcept { return e == static_cast(0); } +constexpr CullingFlags operator~(CullingFlags e) noexcept { + return static_cast(~static_cast>(e)); +} + constexpr bool any(CullingFlags e) noexcept { return !!e; } struct SceneData { SceneData() = default; - SceneData(const scene::RenderScene* sceneIn, const scene::Camera* cameraIn, SceneFlags flagsIn, LightInfo lightIn, CullingFlags cullingFlagsIn) noexcept + SceneData(const scene::RenderScene* sceneIn, const scene::Camera* cameraIn, SceneFlags flagsIn, LightInfo lightIn, CullingFlags cullingFlagsIn, IntrusivePtr shadingLightIn) noexcept : scene(sceneIn), camera(cameraIn), light(std::move(lightIn)), flags(flagsIn), - cullingFlags(cullingFlagsIn) {} + cullingFlags(cullingFlagsIn), + shadingLight(std::move(shadingLightIn)) {} const scene::RenderScene* scene{nullptr}; const scene::Camera* camera{nullptr}; LightInfo light; SceneFlags flags{SceneFlags::NONE}; CullingFlags cullingFlags{CullingFlags::CAMERA_FRUSTUM}; + IntrusivePtr shadingLight; }; struct Dispatch { diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index bec2b17666e..0e0ea222191 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -320,6 +320,10 @@ constexpr bool operator!(SubpassCapabilities e) noexcept { return e == static_cast(0); } +constexpr SubpassCapabilities operator~(SubpassCapabilities e) noexcept { + return static_cast(~static_cast>(e)); +} + constexpr bool any(SubpassCapabilities e) noexcept { return !!e; } From ed1652b56307a4c01952a989a57a153906625de4 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Mon, 18 Sep 2023 17:11:53 +0800 Subject: [PATCH 61/82] [Update] RecyclePool (#176) --- cocos/core/memop/recycle-pool.ts | 28 +------- cocos/rendering/custom/executor.ts | 8 +-- cocos/rendering/custom/scene-culling.ts | 68 ++++++++++---------- cocos/rendering/custom/web-pipeline-types.ts | 24 +++---- cocos/rendering/custom/web-scene.ts | 4 +- 5 files changed, 50 insertions(+), 82 deletions(-) diff --git a/cocos/core/memop/recycle-pool.ts b/cocos/core/memop/recycle-pool.ts index e23a300eb49..ec1aa1a83b7 100644 --- a/cocos/core/memop/recycle-pool.ts +++ b/cocos/core/memop/recycle-pool.ts @@ -24,11 +24,6 @@ import { ScalableContainer } from './scalable-container'; -export class UpdateRecyclePool { - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-empty-function - update (...args: any[]) {} -} - /** * @en Recyclable object pool. It's designed to be entirely reused each time. * There is no put and get method, each time you get the [[data]], you can use all elements as new. @@ -41,7 +36,7 @@ export class UpdateRecyclePool { * @see [[Pool]] */ export class RecyclePool extends ScalableContainer { - private _fn: (...args: any[]) => T; + private _fn: () => T; private _dtor: ((obj: T) => void) | null = null; private _count = 0; private _data: T[]; @@ -54,7 +49,7 @@ export class RecyclePool extends ScalableContainer { * @param size Initial pool size * @param dtor The finalizer of element, it's invoked when this container is destroyed or shrunk */ - constructor (fn: (...args: any[]) => T, size: number, dtor?: (obj: T) => void) { + constructor (fn: () => T, size: number, dtor?: (obj: T) => void) { super(); this._fn = fn; this._dtor = dtor || null; @@ -115,25 +110,6 @@ export class RecyclePool extends ScalableContainer { return this._data[this._count++]; } - /** - * @en Create objects with given parameters. If object creation is parameter-based, it is recommended to start with an initial length of 0. - * @zh 通过给定参数构建对象,如果是通过参数构建对象的方式,建议Pool初始长度为0,并让目标类继承UpdateRecyclePool,便于更新操作。 - */ - public addWithArgs (...args: any[]): T { - const data = this._data[this._count]; - if (data) { - this._count++; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - if (data instanceof UpdateRecyclePool) { data.update(...args); } - return data; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - const newObj = this._fn(...args); // 使用传入的参数创建新对象 - this._data[this._count++] = newObj; - - return newObj; - } - /** * @en Destroy the object pool. Please don't use it any more after it is destroyed. * @zh 销毁对象池。销毁后不能继续使用。 diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 15079212cf2..15e01ec16d3 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1664,19 +1664,19 @@ class ExecutorPools { }), 64); } addDeviceQueue (): DeviceRenderQueue { - return this.deviceQueuePool.addWithArgs(); + return this.deviceQueuePool.add(); } addComputeQueue (): DeviceComputeQueue { return this.computeQueuePool.add(); } addGraphScene (): GraphScene { - return this.graphScenePool.addWithArgs(); + return this.graphScenePool.add(); } addReflectionProbe (): RenderReflectionProbeQueue { - return this.reflectionProbe.addWithArgs(); + return this.reflectionProbe.add(); } addRasterPassInfo (): RasterPassInfo { - return this.rasterPassInfoPool.addWithArgs(); + return this.rasterPassInfoPool.add(); } addComputePassInfo (): ComputePassInfo { return this.computePassInfoPool.add(); diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 9c317488415..8a8e001ab93 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -1,9 +1,9 @@ -import { Vec3, assert, RecyclePool, UpdateRecyclePool, cclegacy } from '../../core'; +import { Vec3, assert, RecyclePool } from '../../core'; import { Frustum, intersect, AABB } from '../../core/geometry'; import { CommandBuffer } from '../../gfx'; -import { BatchingSchemes, IMacroPatch, Pass, RenderScene } from '../../render-scene'; -import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, ProbeType, - ReflectionProbe, SKYBOX_FLAG, ShadowType, SpotLight, SubModel } from '../../render-scene/scene'; +import { BatchingSchemes, Pass, RenderScene } from '../../render-scene'; +import { CSMLevel, Camera, DirectionalLight, LightType, Model, ProbeType, + ReflectionProbe, SKYBOX_FLAG, ShadowType, SpotLight } from '../../render-scene/scene'; import { Layers, Node } from '../../scene-graph'; import { PipelineSceneData } from '../pipeline-scene-data'; import { hashCombineStr, getSubpassOrPassID, bool } from './define'; @@ -14,19 +14,12 @@ import { RenderQueue, RenderQueueDesc, instancePool } from './web-pipeline-types import { ObjectPool } from './utils'; const vec3Pool = new ObjectPool(() => new Vec3()); -const cullingKeyRecycle = new RecyclePool(( - sceneData: SceneData, - castShadows: boolean, - sceneId: number, -) => new CullingKey(sceneData, castShadows, sceneId), 0); -const cullingQueriesRecycle = new RecyclePool(() => new CullingQueries(), 0); -const renderQueueRecycle = new RecyclePool(() => new RenderQueue(), 0); -const renderQueueDescRecycle = new RecyclePool(( - culledSource: number, - renderQueueTarget: number, - lightType: LightType, -) => new RenderQueueDesc(culledSource, renderQueueTarget, lightType), 0); - +class CullingPools { + cullingKeyRecycle = new RecyclePool(() => new CullingKey(), 8); + cullingQueriesRecycle = new RecyclePool(() => new CullingQueries(), 8); + renderQueueRecycle = new RecyclePool(() => new RenderQueue(), 8); + renderQueueDescRecycle = new RecyclePool(() => new RenderQueueDesc(), 8); +} const REFLECTION_PROBE_DEFAULT_MASK = Layers.makeMaskExclude([Layers.BitMask.UI_2D, Layers.BitMask.UI_3D, Layers.BitMask.GIZMOS, Layers.BitMask.EDITOR, Layers.BitMask.SCENE_GIZMO, Layers.BitMask.PROFILER]); @@ -82,15 +75,14 @@ function computeCullingKey ( return hashCode; } -class CullingKey extends UpdateRecyclePool { - sceneData: SceneData; +class CullingKey { + sceneData: SceneData | null = null; castShadows = false; - constructor (sceneData: SceneData, castShadows: boolean, verId: number) { - super(); + constructor (sceneData: SceneData | null = null, castShadows: boolean = false) { this.sceneData = sceneData; this.castShadows = castShadows; } - update (sceneData: SceneData, castShadows: boolean, verId: number): void { + update (sceneData: SceneData, castShadows: boolean): void { this.sceneData = sceneData; this.castShadows = castShadows; } @@ -98,7 +90,7 @@ class CullingKey extends UpdateRecyclePool { let pSceneData: PipelineSceneData; -class CullingQueries extends UpdateRecyclePool { +class CullingQueries { // key: hash val culledResultIndex: Map = new Map(); cullingKeyResult: Map = new Map(); @@ -274,6 +266,7 @@ export class SceneCulling { culledResults: Array> = new Array>(); renderQueues: Array = new Array(); sceneQueryIndex: Map = new Map(); + cullingPools = new CullingPools(); // source id numCullingQueries = 0; // target id @@ -281,10 +274,10 @@ export class SceneCulling { layoutGraph; renderGraph; resetPool (): void { - cullingKeyRecycle.reset(); - cullingQueriesRecycle.reset(); - renderQueueRecycle.reset(); - renderQueueDescRecycle.reset(); + this.cullingPools.cullingKeyRecycle.reset(); + this.cullingPools.cullingQueriesRecycle.reset(); + this.cullingPools.renderQueueRecycle.reset(); + this.cullingPools.renderQueueDescRecycle.reset(); instancePool.reset(); } clear (): void { @@ -311,7 +304,9 @@ export class SceneCulling { const scene = sceneData.scene!; let queries = this.sceneQueries.get(scene); if (!queries) { - this.sceneQueries.set(scene, cullingQueriesRecycle.addWithArgs()); + const cullingQuery = this.cullingPools.cullingQueriesRecycle.add(); + cullingQuery.update(); + this.sceneQueries.set(scene, cullingQuery); queries = this.sceneQueries.get(scene); } const castShadow: boolean = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); @@ -326,11 +321,12 @@ export class SceneCulling { this.culledResults.push([]); } queries!.culledResultIndex.set(key, sourceID); - queries!.cullingKeyResult.set(key, cullingKeyRecycle.addWithArgs( + const cullingKey = this.cullingPools.cullingKeyRecycle.add(); + cullingKey.update( sceneData, castShadow, - sceneId, - )); + ); + queries!.cullingKeyResult.set(key, cullingKey); return sourceID; } @@ -338,7 +334,9 @@ export class SceneCulling { const targetID = this.numRenderQueues++; if (this.numRenderQueues > this.renderQueues.length) { assert(this.numRenderQueues === (this.renderQueues.length + 1)); - this.renderQueues.push(renderQueueRecycle.addWithArgs()); + const renderQueue = this.cullingPools.renderQueueRecycle.add(); + renderQueue.update(); + this.renderQueues.push(renderQueue); } assert(targetID < this.renderQueues.length); const rq = this.renderQueues[targetID]; @@ -362,8 +360,10 @@ export class SceneCulling { const targetID = this.createRenderQueue(sceneData.flags, layoutID); const lightType = sceneData.light.light ? sceneData.light.light.type : LightType.UNKNOWN; + const renderQueueDesc = this.cullingPools.renderQueueDescRecycle.add(); + renderQueueDesc.update(sourceID, targetID, lightType); // add render queue to query source - this.sceneQueryIndex.set(v, renderQueueDescRecycle.addWithArgs(sourceID, targetID, lightType)); + this.sceneQueryIndex.set(v, renderQueueDesc); } } @@ -389,7 +389,7 @@ export class SceneCulling { assert(!!scene); for (const [key, sourceID] of queries.culledResultIndex) { const cullingKey = queries.cullingKeyResult.get(key)!; - const sceneData = cullingKey.sceneData; + const sceneData = cullingKey.sceneData!; assert(!!sceneData.camera); assert(sceneData.camera.scene === scene); const camera = sceneData.camera; diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index dd8fb863361..52b3ecccb7a 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -1,4 +1,4 @@ -import { RecyclePool, UpdateRecyclePool, cclegacy } from '../../core'; +import { RecyclePool, cclegacy } from '../../core'; import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; import { IMacroPatch } from '../../render-scene'; import { LightType, Model, SubModel } from '../../render-scene/scene'; @@ -7,7 +7,7 @@ import { InstancedBuffer } from '../instanced-buffer'; import { PipelineStateManager } from '../pipeline-state-manager'; import { SceneFlags } from './types'; -export class DrawInstance extends UpdateRecyclePool { +export class DrawInstance { subModel: SubModel | null; priority: number; hash: number; @@ -23,7 +23,6 @@ export class DrawInstance extends UpdateRecyclePool { shaderID = 0, passIndex = 0, ) { - super(); this.subModel = subModel; this.priority = priority; this.hash = hash; @@ -48,14 +47,7 @@ export class DrawInstance extends UpdateRecyclePool { } } -export const instancePool = new RecyclePool(( - subModel: SubModel | null = null, - priority: number = 0, - hash: number = 0, - depth: number = 0, - shaderID: number = 0, - passIndex: number = 0, -) => new DrawInstance(subModel, priority, hash, depth, shaderID, passIndex), 0); +export const instancePool = new RecyclePool(() => new DrawInstance(), 8); const CC_USE_RGBE_OUTPUT = 'CC_USE_RGBE_OUTPUT'; function getLayoutId (passLayout: string, phaseLayout: string): number { @@ -135,8 +127,9 @@ export class RenderDrawQueue { const shaderId = subModel.shaders[passIdx].typedID; const hash = (0 << 30) | (passPriority as number << 16) | (modelPriority as number << 8) | passIdx; const priority = model.priority; - - this.instances.push(instancePool.addWithArgs(subModel, priority, hash, depth, shaderId, passIdx)); + const instance = instancePool.add(); + instance.update(subModel, priority, hash, depth, shaderId, passIdx); + this.instances.push(instance); } /** * @en Comparison sorting function. Opaque objects are sorted by priority -> depth front to back -> shader ID. @@ -265,7 +258,7 @@ export class RenderInstancingQueue { } } -export class RenderQueueDesc extends UpdateRecyclePool { +export class RenderQueueDesc { culledSource: number; renderQueueTarget: number; lightType: LightType; @@ -275,7 +268,6 @@ export class RenderQueueDesc extends UpdateRecyclePool { renderQueueTargetIn = 0xFFFFFFFF, lightTypeIn: LightType = LightType.UNKNOWN, ) { - super(); this.culledSource = culledSourceIn; this.renderQueueTarget = renderQueueTargetIn; this.lightType = lightTypeIn; @@ -291,7 +283,7 @@ export class RenderQueueDesc extends UpdateRecyclePool { } } -export class RenderQueue extends UpdateRecyclePool { +export class RenderQueue { probeQueue: ProbeHelperQueue = new ProbeHelperQueue(); opaqueQueue: RenderDrawQueue = new RenderDrawQueue(); transparentQueue: RenderDrawQueue = new RenderDrawQueue(); diff --git a/cocos/rendering/custom/web-scene.ts b/cocos/rendering/custom/web-scene.ts index ea0272151da..168d3c0d556 100644 --- a/cocos/rendering/custom/web-scene.ts +++ b/cocos/rendering/custom/web-scene.ts @@ -136,13 +136,13 @@ export class WebSceneTask implements SceneTask { } public start (): void { - this._sceneCulling(); + // do nothing } public join (): void { // for web-pipeline, do nothing } public submit (): void { - + // do nothing } get camera (): scene.Camera | null { return this._camera; } get renderScene (): RenderScene | null { From 1f57f3b152f559f52c35a95bc37e4895a4bd5a15 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 19 Sep 2023 19:05:46 +0800 Subject: [PATCH 62/82] multi light added --- editor/assets/primitives.fbx.meta | 73 +++----- .../pipeline/custom/NativeBuiltinUtils.cpp | 138 +++++++++++++++ .../pipeline/custom/NativeBuiltinUtils.h | 7 + .../pipeline/custom/NativeExecutor.cpp | 31 ++-- .../pipeline/custom/NativePipeline.cpp | 1 + .../pipeline/custom/NativePipelineFwd.h | 2 + .../pipeline/custom/NativePipelineTypes.cpp | 11 +- .../pipeline/custom/NativePipelineTypes.h | 62 ++++++- .../pipeline/custom/NativeRenderGraph.cpp | 8 +- .../pipeline/custom/NativeRenderQueue.cpp | 41 +++-- .../pipeline/custom/NativeSceneCulling.cpp | 160 +++++++++++++++++- .../renderer/pipeline/custom/NativeSetter.cpp | 1 + .../renderer/pipeline/custom/details/Map.h | 40 +++++ 13 files changed, 485 insertions(+), 90 deletions(-) diff --git a/editor/assets/primitives.fbx.meta b/editor/assets/primitives.fbx.meta index fdc6e41562b..cc3453b08e8 100644 --- a/editor/assets/primitives.fbx.meta +++ b/editor/assets/primitives.fbx.meta @@ -19,8 +19,8 @@ ], "subMetas": {}, "userData": { - "gltfIndex": 5, - "triangleCount": 1512 + "gltfIndex": 4, + "triangleCount": 2380 } }, "801ec": { @@ -59,12 +59,12 @@ "triangleCount": 200 } }, - "40ece": { + "38fd2": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@40ece", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", "displayName": "", - "id": "40ece", - "name": "torus.mesh", + "id": "38fd2", + "name": "cone.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -74,15 +74,15 @@ "subMetas": {}, "userData": { "gltfIndex": 2, - "triangleCount": 2048 + "triangleCount": 72 } }, - "fc873": { + "40ece": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@fc873", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@40ece", "displayName": "", - "id": "fc873", - "name": "quad.mesh", + "id": "40ece", + "name": "torus.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -92,15 +92,15 @@ "subMetas": {}, "userData": { "gltfIndex": 3, - "triangleCount": 2 + "triangleCount": 2048 } }, - "a804a": { + "fc873": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@fc873", "displayName": "", - "id": "a804a", - "name": "box.mesh", + "id": "fc873", + "name": "quad.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -109,8 +109,8 @@ ], "subMetas": {}, "userData": { - "gltfIndex": 4, - "triangleCount": 12 + "gltfIndex": 5, + "triangleCount": 2 } }, "8abdc": { @@ -128,15 +128,15 @@ "subMetas": {}, "userData": { "gltfIndex": 6, - "triangleCount": 112 + "triangleCount": 128 } }, - "38fd2": { + "a804a": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", "displayName": "", - "id": "38fd2", - "name": "cone.mesh", + "id": "a804a", + "name": "box.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -146,25 +146,9 @@ "subMetas": {}, "userData": { "gltfIndex": 7, - "triangleCount": 64 + "triangleCount": 12 } }, - "7a3ca": { - "importer": "gltf-material", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@7a3ca", - "displayName": "", - "id": "7a3ca", - "name": "lambert2.material", - "userData": { - "gltfIndex": 0 - }, - "ver": "1.0.14", - "imported": true, - "files": [ - ".json" - ], - "subMetas": {} - }, "8d883": { "importer": "gltf-material", "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@8d883", @@ -172,7 +156,7 @@ "id": "8d883", "name": "lambert1.material", "userData": { - "gltfIndex": 1 + "gltfIndex": 0 }, "ver": "1.0.14", "imported": true, @@ -219,15 +203,14 @@ "meshes": [ "1263d74c-8167-4928-91a6-4e2672411f47@801ec", "1263d74c-8167-4928-91a6-4e2672411f47@2e76e", + "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", "1263d74c-8167-4928-91a6-4e2672411f47@40ece", - "1263d74c-8167-4928-91a6-4e2672411f47@fc873", - "1263d74c-8167-4928-91a6-4e2672411f47@a804a", "1263d74c-8167-4928-91a6-4e2672411f47@17020", + "1263d74c-8167-4928-91a6-4e2672411f47@fc873", "1263d74c-8167-4928-91a6-4e2672411f47@8abdc", - "1263d74c-8167-4928-91a6-4e2672411f47@38fd2" + "1263d74c-8167-4928-91a6-4e2672411f47@a804a" ], "materials": [ - "1263d74c-8167-4928-91a6-4e2672411f47@7a3ca", "1263d74c-8167-4928-91a6-4e2672411f47@8d883" ], "scenes": [ diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp index 2aebd316999..9f408052350 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp @@ -26,6 +26,7 @@ #include "cocos/application/ApplicationManager.h" #include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/gfx-base/GFXDevice.h" +#include "cocos/renderer/pipeline/Define.h" #include "cocos/renderer/pipeline/PipelineSceneData.h" #include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" #include "cocos/renderer/pipeline/custom/NativePipelineTypes.h" @@ -537,6 +538,143 @@ void setLegacyTextureUBOView( // setTextureImpl(data, layoutGraph, "cc_spotShadowMap", BuiltinResMgr::getInstance()->get("default-texture")->getGFXTexture()); } +namespace { + +float kLightMeterScale{10000.0F}; + +} // namespace + +void setLightUBO( + const scene::Light *light, bool bHDR, float exposure, + const scene::Shadows *shadowInfo, + char *buffer, size_t bufferSize) { + CC_EXPECTS(bufferSize % sizeof(float) == 0); + const auto maxSize = bufferSize / sizeof(float); + auto *lightBufferData = reinterpret_cast(buffer); + + size_t offset = 0; + + Vec3 position = Vec3(0.0F, 0.0F, 0.0F); + float size = 0.F; + float range = 0.F; + float luminanceHDR = 0.F; + float luminanceLDR = 0.F; + if (light->getType() == scene::LightType::SPHERE) { + const auto *sphereLight = static_cast(light); + position = sphereLight->getPosition(); + size = sphereLight->getSize(); + range = sphereLight->getRange(); + luminanceHDR = sphereLight->getLuminanceHDR(); + luminanceLDR = sphereLight->getLuminanceLDR(); + } else if (light->getType() == scene::LightType::SPOT) { + const auto *spotLight = static_cast(light); + position = spotLight->getPosition(); + size = spotLight->getSize(); + range = spotLight->getRange(); + luminanceHDR = spotLight->getLuminanceHDR(); + luminanceLDR = spotLight->getLuminanceLDR(); + } else if (light->getType() == scene::LightType::POINT) { + const auto *pointLight = static_cast(light); + position = pointLight->getPosition(); + size = 0.0F; + range = pointLight->getRange(); + luminanceHDR = pointLight->getLuminanceHDR(); + luminanceLDR = pointLight->getLuminanceLDR(); + } else if (light->getType() == scene::LightType::RANGED_DIRECTIONAL) { + const auto *rangedDirLight = static_cast(light); + position = rangedDirLight->getPosition(); + size = 0.0F; + range = 0.0F; + luminanceHDR = rangedDirLight->getIlluminanceHDR(); + luminanceLDR = rangedDirLight->getIlluminanceLDR(); + } + auto index = offset + pipeline::UBOForwardLight::LIGHT_POS_OFFSET; + CC_EXPECTS(index + 4 < maxSize); + lightBufferData[index++] = position.x; + lightBufferData[index++] = position.y; + lightBufferData[index] = position.z; + + index = offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET; + CC_EXPECTS(index + 4 < maxSize); + lightBufferData[index++] = size; + lightBufferData[index] = range; + + index = offset + pipeline::UBOForwardLight::LIGHT_COLOR_OFFSET; + CC_EXPECTS(index + 4 < maxSize); + const auto &color = light->getColor(); + if (light->isUseColorTemperature()) { + const auto &tempRGB = light->getColorTemperatureRGB(); + lightBufferData[index++] = color.x * tempRGB.x; + lightBufferData[index++] = color.y * tempRGB.y; + lightBufferData[index++] = color.z * tempRGB.z; + } else { + lightBufferData[index++] = color.x; + lightBufferData[index++] = color.y; + lightBufferData[index++] = color.z; + } + + if (bHDR) { + lightBufferData[index] = luminanceHDR * exposure * kLightMeterScale; + } else { + lightBufferData[index] = luminanceLDR; + } + + switch (light->getType()) { + case scene::LightType::SPHERE: + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_POS_OFFSET + 3] = + static_cast(scene::LightType::SPHERE); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = 0; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0; + break; + case scene::LightType::SPOT: { + const auto *spotLight = static_cast(light); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_POS_OFFSET + 3] = static_cast(scene::LightType::SPOT); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = spotLight->getSpotAngle(); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = + (shadowInfo->isEnabled() && + spotLight->isShadowEnabled() && + shadowInfo->getType() == scene::ShadowType::SHADOW_MAP) + ? 1.0F + : 0.0F; + + index = offset + pipeline::UBOForwardLight::LIGHT_DIR_OFFSET; + const auto &direction = spotLight->getDirection(); + lightBufferData[index++] = direction.x; + lightBufferData[index++] = direction.y; + lightBufferData[index] = direction.z; + } break; + case scene::LightType::POINT: + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_POS_OFFSET + 3] = static_cast(scene::LightType::POINT); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = 0; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0; + break; + case scene::LightType::RANGED_DIRECTIONAL: { + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_POS_OFFSET + 3] = static_cast(scene::LightType::RANGED_DIRECTIONAL); + + const auto *rangedDirLight = static_cast(light); + const Vec3 &right = rangedDirLight->getRight(); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 0] = right.x; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 1] = right.y; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = right.z; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0; + + const auto &direction = rangedDirLight->getDirection(); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_DIR_OFFSET + 0] = direction.x; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_DIR_OFFSET + 1] = direction.y; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_DIR_OFFSET + 2] = direction.z; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_DIR_OFFSET + 3] = 0; + + const auto &scale = rangedDirLight->getScale(); + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_BOUNDING_SIZE_VS_OFFSET + 0] = scale.x * 0.5F; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_BOUNDING_SIZE_VS_OFFSET + 1] = scale.y * 0.5F; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_BOUNDING_SIZE_VS_OFFSET + 2] = scale.z * 0.5F; + lightBufferData[offset + pipeline::UBOForwardLight::LIGHT_BOUNDING_SIZE_VS_OFFSET + 3] = 0; + } break; + default: + break; + } +} + const BuiltinCascadedShadowMap *getBuiltinShadowCSM( const PipelineRuntime &pplRuntime, const scene::Camera &camera, diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h index 1b1d8ebb6a2..9d5ad1814e1 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h @@ -37,6 +37,7 @@ namespace scene { class Camera; class Light; class DirectionalLight; +class Shadows; } // namespace scene namespace geometry { @@ -84,6 +85,12 @@ void setShadowUBOLightView( uint32_t level, RenderData &data); +// Additive light +void setLightUBO( + const scene::Light *light, bool bHDR, float exposure, + const scene::Shadows *shadowInfo, + char *buffer, size_t bufferSize); + // Render graph void updateRasterPassConstants(uint32_t width, uint32_t height, Setter &setter); diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 451942a2ff7..78c45082cb6 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -28,6 +28,7 @@ #include "LayoutGraphGraphs.h" #include "LayoutGraphTypes.h" #include "LayoutGraphUtils.h" +#include "NativeBuiltinUtils.h" #include "NativePipelineFwd.h" #include "NativePipelineTypes.h" #include "NativeRenderGraphUtils.h" @@ -991,9 +992,6 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { updateAndCreatePerPassDescriptorSet(vertID); ctx.currentProjMatrix = sceneData.camera->getMatProj(); } - if (sceneData.shadingLight && !dynamic_cast(sceneData.shadingLight.get())) { - - } } else if (holds(vertID, ctx.g)) { const auto& blit = get(BlitTag{}, vertID, ctx.g); if (blit.camera) { @@ -1385,14 +1383,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { const auto* scene = camera->getScene(); const auto& queueDesc = ctx.context.sceneCulling.renderQueueIndex.at(sceneID); const auto& queue = ctx.context.sceneCulling.renderQueues[queueDesc.renderQueueTarget.value]; - queue.opaqueQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); - queue.opaqueInstancingQueue.recordCommandBuffer( - ctx.currentPass, ctx.cmdBuff); - queue.transparentQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); - queue.transparentInstancingQueue.recordCommandBuffer( - ctx.currentPass, ctx.cmdBuff); + + queue.recordCommands(ctx.cmdBuff, ctx.currentPass, 0); + if (any(sceneData.flags & SceneFlags::REFLECTION_PROBE)) { queue.probeQueue.removeMacro(); } @@ -1998,6 +1991,16 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { } } + // light manangement + { + auto& ctx = ppl.nativeContext; + ctx.lightResources.clear(); + ctx.lightResources.buildLights( + ctx.sceneCulling, + ppl.pipelineSceneData->isHDR(), + ppl.pipelineSceneData->getShadows()); + } + // gpu driven if constexpr (ENABLE_GPU_DRIVEN) { // TODO(jilin): consider populating renderSceneResources here @@ -2019,6 +2022,7 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { // upload buffers { + // scene const auto& sceneCulling = ppl.nativeContext.sceneCulling; for (uint32_t queueID = 0; queueID != sceneCulling.numRenderQueues; ++queueID) { // notice: we cannot use ranged-for of sceneCulling.renderQueues @@ -2027,6 +2031,11 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { queue.opaqueInstancingQueue.uploadBuffers(submit.primaryCommandBuffer); queue.transparentInstancingQueue.uploadBuffers(submit.primaryCommandBuffer); } + + // lights + auto& ctx = ppl.nativeContext; + ctx.lightResources.buildLightBuffer(submit.primaryCommandBuffer); + ctx.lightResources.tryUpdateRenderSceneLocalDescriptorSet(sceneCulling); } ccstd::pmr::unordered_map< diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index da2643078ad..85cec43b9cf 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -1195,6 +1195,7 @@ bool NativePipeline::activate(gfx::Swapchain *swapchainIn) { const auto &lg = programLibrary->layoutGraph; const auto numNodes = num_vertices(lg); nativeContext.layoutGraphResources.reserve(numNodes); + nativeContext.lightResources.init(*programLibrary, device, 16); for (uint32_t i = 0; i != numNodes; ++i) { auto &node = nativeContext.layoutGraphResources.emplace_back(); diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 29fc3204c2d..f83927c1b64 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -91,7 +91,9 @@ struct LightBoundsCullingKey; struct LightBoundsCulling; struct NativeRenderQueueID; struct NativeRenderQueueDesc; +struct LightBoundsCullingResult; struct SceneCulling; +struct LightResource; struct NativeRenderContext; class NativeProgramLibrary; struct PipelineCustomization; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index 1d4f2cdc285..4046c22bc68 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp @@ -90,7 +90,8 @@ NativeRenderQueue::NativeRenderQueue(NativeRenderQueue&& rhs, const allocator_ty opaqueInstancingQueue(std::move(rhs.opaqueInstancingQueue), alloc), transparentInstancingQueue(std::move(rhs.transparentInstancingQueue), alloc), sceneFlags(rhs.sceneFlags), - subpassOrPassLayoutID(rhs.subpassOrPassLayoutID) {} + subpassOrPassLayoutID(rhs.subpassOrPassLayoutID), + lightByteOffset(rhs.lightByteOffset) {} ResourceGroup::ResourceGroup(const allocator_type& alloc) noexcept : instancingBuffers(alloc) {} @@ -209,12 +210,18 @@ SceneCulling::SceneCulling(SceneCulling&& rhs, const allocator_type& alloc) numRenderQueues(rhs.numRenderQueues), gpuCullingPassID(rhs.gpuCullingPassID) {} +LightResource::LightResource(const allocator_type& alloc) noexcept +: cpuBuffer(alloc), + lights(alloc), + lightIndex(alloc) {} + NativeRenderContext::NativeRenderContext(std::unique_ptr defaultResourceIn, const allocator_type& alloc) noexcept : defaultResource(std::move(defaultResourceIn)), resourceGroups(alloc), layoutGraphResources(alloc), renderSceneResources(alloc), - sceneCulling(alloc) {} + sceneCulling(alloc), + lightResources(alloc) {} NativeProgramLibrary::NativeProgramLibrary(const allocator_type& alloc) noexcept : layoutGraph(alloc), diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 06216cc2e83..c17bd4871b5 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -995,9 +995,9 @@ struct RenderInstancingQueue { void sort(); void uploadBuffers(gfx::CommandBuffer *cmdBuffer) const; void recordCommandBuffer( - gfx::RenderPass *renderPass, gfx::CommandBuffer *cmdBuffer, - gfx::DescriptorSet *ds = nullptr, uint32_t offset = 0, - const ccstd::vector *dynamicOffsets = nullptr) const; + gfx::RenderPass *renderPass, uint32_t subpassIndex, + gfx::CommandBuffer *cmdBuffer, + uint32_t lightByteOffset = 0xFFFFFFFF) const; ccstd::pmr::vector sortedBatches; PmrUnorderedMap passInstances; @@ -1061,9 +1061,10 @@ struct RenderDrawQueue { void add(const scene::Model& model, float depth, uint32_t subModelIdx, uint32_t passIdx); void sortOpaqueOrCutout(); void sortTransparent(); - void recordCommandBuffer(gfx::Device *device, const scene::Camera *camera, - gfx::RenderPass *renderPass, gfx::CommandBuffer *cmdBuffer, - uint32_t subpassIndex) const; + void recordCommandBuffer( + gfx::RenderPass *renderPass, uint32_t subpassIndex, + gfx::CommandBuffer *cmdBuffer, + uint32_t lightByteOffset = 0xFFFFFFFF) const; ccstd::pmr::vector instances; }; @@ -1086,6 +1087,8 @@ struct NativeRenderQueue { void sort(); void clear() noexcept; bool empty() const noexcept; + void recordCommands( + gfx::CommandBuffer *cmdBuffer, gfx::RenderPass *renderPass, uint32_t subpassIndex) const; RenderDrawQueue opaqueQueue; RenderDrawQueue transparentQueue; @@ -1094,6 +1097,7 @@ struct NativeRenderQueue { RenderInstancingQueue transparentInstancingQueue; SceneFlags sceneFlags{SceneFlags::NONE}; uint32_t subpassOrPassLayoutID{0xFFFFFFFF}; + uint32_t lightByteOffset{0xFFFFFFFF}; }; struct ResourceGroup { @@ -1219,7 +1223,7 @@ struct LayoutGraphNodeResource { LayoutGraphNodeResource& operator=(LayoutGraphNodeResource const& rhs) = delete; void syncResources() noexcept; - PmrFlatMap uniformBuffers; + ccstd::pmr::unordered_map uniformBuffers; DescriptorSetPool descriptorSetPool; PmrTransparentMap programResources; }; @@ -1369,6 +1373,11 @@ struct NativeRenderQueueDesc { scene::LightType lightType{scene::LightType::UNKNOWN}; }; +struct LightBoundsCullingResult { + ccstd::vector instances; + uint32_t lightByteOffset{0xFFFFFFFF}; +}; + struct SceneCulling { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT @@ -1397,7 +1406,7 @@ struct SceneCulling { ccstd::pmr::unordered_map frustumCullings; ccstd::pmr::vector> frustumCullingResults; ccstd::pmr::unordered_map lightBoundsCullings; - ccstd::pmr::vector> lightBoundsCullingResults; + ccstd::pmr::vector lightBoundsCullingResults; ccstd::pmr::vector renderQueues; PmrFlatMap renderQueueIndex; uint32_t numFrustumCulling{0}; @@ -1406,6 +1415,42 @@ struct SceneCulling { uint32_t gpuCullingPassID{0xFFFFFFFF}; }; +struct LightResource { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {cpuBuffer.get_allocator().resource()}; + } + + LightResource(const allocator_type& alloc) noexcept; // NOLINT + LightResource(LightResource&& rhs) = delete; + LightResource(LightResource const& rhs) = delete; + LightResource& operator=(LightResource&& rhs) = delete; + LightResource& operator=(LightResource const& rhs) = delete; + + void init(const NativeProgramLibrary& programLib, gfx::Device* deviceIn, uint32_t maxNumLights); + void buildLights( + SceneCulling& sceneCulling, + bool bHDR, + const scene::Shadows* shadowInfo); + void tryUpdateRenderSceneLocalDescriptorSet(const SceneCulling& sceneCulling); + void clear(); + + uint32_t addLight(const scene::Light* light, bool bHDR, float exposure, const scene::Shadows *shadowInfo); + void buildLightBuffer(gfx::CommandBuffer* cmdBuffer) const; + + ccstd::pmr::vector cpuBuffer; + const NativeProgramLibrary* programLibrary{nullptr}; + gfx::Device* device{nullptr}; + uint32_t elementSize{0}; + uint32_t maxNumLights{16}; + uint32_t binding{0xFFFFFFFF}; + bool resized{false}; + IntrusivePtr lightBuffer; + IntrusivePtr firstLightBufferView; + ccstd::pmr::vector lights; + PmrFlatMap lightIndex; +}; + struct NativeRenderContext { using allocator_type = boost::container::pmr::polymorphic_allocator; allocator_type get_allocator() const noexcept { // NOLINT @@ -1427,6 +1472,7 @@ struct NativeRenderContext { ccstd::pmr::unordered_map renderSceneResources; QuadResource fullscreenQuad; SceneCulling sceneCulling; + LightResource lightResources; }; class NativeProgramLibrary final : public ProgramLibrary { diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index f299e21eca5..304f76fbf5d 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -818,13 +818,11 @@ SceneBuilder *NativeRenderQueueBuilder::addScene( // objects are projected to camera, set camera ubo builder->setBuiltinCameraConstants(camera); - if (const auto *pDirLight = camera->getScene()->getMainLight(); pDirLight) { + if (const auto *pDirLight = dynamic_cast(light); pDirLight) { // light is directional builder->setBuiltinDirectionalLightConstants(pDirLight, camera); - } else if (light) { - // light is non-directional - // builder->setBuiltinXxxLightConstants(light, camera); - CC_EXPECTS(false); + } else if (light) { // light is non-directional + // TODO(zhouzhenglong): refactor per-instance lighting } // set builtin legacy ubo diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp index 41525f49df2..d4b4f4c9d69 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp @@ -26,6 +26,7 @@ #include #include "NativePipelineTypes.h" #include "cocos/renderer/pipeline/Define.h" +#include "cocos/renderer/pipeline/InstancedBuffer.h" #include "cocos/renderer/pipeline/PipelineStateManager.h" #include "cocos/renderer/pipeline/custom/LayoutGraphGraphs.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" @@ -131,9 +132,9 @@ void RenderDrawQueue::sortTransparent() { } void RenderDrawQueue::recordCommandBuffer( - gfx::Device * /*device*/, const scene::Camera * /*camera*/, - gfx::RenderPass *renderPass, gfx::CommandBuffer *cmdBuff, - uint32_t subpassIndex) const { + gfx::RenderPass *renderPass, uint32_t subpassIndex, + gfx::CommandBuffer *cmdBuff, + uint32_t lightByteOffset) const { for (const auto &instance : instances) { const auto *subModel = instance.subModel; @@ -145,7 +146,11 @@ void RenderDrawQueue::recordCommandBuffer( cmdBuff->bindPipelineState(pso); cmdBuff->bindDescriptorSet(pipeline::materialSet, pass->getDescriptorSet()); - cmdBuff->bindDescriptorSet(pipeline::localSet, subModel->getDescriptorSet()); + if (lightByteOffset != 0xFFFFFFFF) { + cmdBuff->bindDescriptorSet(pipeline::localSet, subModel->getDescriptorSet(), 1, &lightByteOffset); + } else { + cmdBuff->bindDescriptorSet(pipeline::localSet, subModel->getDescriptorSet()); + } cmdBuff->bindInputAssembler(inputAssembler); cmdBuff->draw(inputAssembler); } @@ -207,8 +212,9 @@ void RenderInstancingQueue::uploadBuffers(gfx::CommandBuffer *cmdBuffer) const { } void RenderInstancingQueue::recordCommandBuffer( - gfx::RenderPass *renderPass, gfx::CommandBuffer *cmdBuffer, - gfx::DescriptorSet *ds, uint32_t offset, const ccstd::vector *dynamicOffsets) const { + gfx::RenderPass *renderPass, uint32_t subpassIndex, + gfx::CommandBuffer *cmdBuffer, + uint32_t lightByteOffset) const { // const auto &renderQueue = sortedBatches; for (const auto *instanceBuffer : renderQueue) { if (!instanceBuffer->hasPendingModels()) { @@ -223,16 +229,13 @@ void RenderInstancingQueue::recordCommandBuffer( continue; } auto *pso = pipeline::PipelineStateManager::getOrCreatePipelineState( - drawPass, instance.shader, instance.ia, renderPass); + drawPass, instance.shader, instance.ia, renderPass, subpassIndex); if (lastPSO != pso) { cmdBuffer->bindPipelineState(pso); lastPSO = pso; } - if (ds) { - cmdBuffer->bindDescriptorSet(pipeline::globalSet, ds, 1, &offset); - } - if (dynamicOffsets) { - cmdBuffer->bindDescriptorSet(pipeline::localSet, instance.descriptorSet, *dynamicOffsets); + if (lightByteOffset != 0xFFFFFFFF) { + cmdBuffer->bindDescriptorSet(pipeline::localSet, instance.descriptorSet, 1, &lightByteOffset); } else { cmdBuffer->bindDescriptorSet(pipeline::localSet, instance.descriptorSet, instanceBuffer->dynamicOffsets()); } @@ -249,6 +252,20 @@ void NativeRenderQueue::sort() { transparentInstancingQueue.sort(); } +void NativeRenderQueue::recordCommands( + gfx::CommandBuffer *cmdBuffer, + gfx::RenderPass *renderPass, + uint32_t subpassIndex) const { + opaqueQueue.recordCommandBuffer( + renderPass, subpassIndex, cmdBuffer, lightByteOffset); + opaqueInstancingQueue.recordCommandBuffer( + renderPass, subpassIndex, cmdBuffer, lightByteOffset); + transparentQueue.recordCommandBuffer( + renderPass, subpassIndex, cmdBuffer, lightByteOffset); + transparentInstancingQueue.recordCommandBuffer( + renderPass, subpassIndex, cmdBuffer, lightByteOffset); +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index a9faffcf002..cc805461604 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -1,4 +1,5 @@ #include "cocos/renderer/pipeline/Define.h" +#include "cocos/renderer/pipeline/custom/LayoutGraphUtils.h" #include "cocos/renderer/pipeline/custom/NativeBuiltinUtils.h" #include "cocos/renderer/pipeline/custom/NativePipelineTypes.h" #include "cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h" @@ -10,10 +11,14 @@ #include "cocos/scene/Skybox.h" #include "cocos/scene/SpotLight.h" +#include + namespace cc { namespace render { + const static uint32_t REFLECTION_PROBE_DEFAULT_MASK = ~static_cast(pipeline::LayerList::UI_2D) & ~static_cast(pipeline::LayerList::PROFILER) & ~static_cast(pipeline::LayerList::UI_3D) & ~static_cast(pipeline::LayerList::GIZMOS) & ~static_cast(pipeline::LayerList::SCENE_GIZMO) & ~static_cast(pipeline::LayerList::EDITOR); + void NativeRenderQueue::clear() noexcept { probeQueue.clear(); opaqueQueue.instances.clear(); @@ -433,27 +438,27 @@ void SceneCulling::batchLightBoundsCulling() { CC_EXPECTS(key.camera->getScene() == scene); const auto& frustumCullingResult = frustumCullingResults.at(key.frustumCullingID.value); auto& lightBoundsCullingResult = lightBoundsCullingResults.at(cullingID.value); - CC_EXPECTS(lightBoundsCullingResult.empty()); + CC_EXPECTS(lightBoundsCullingResult.instances.empty()); switch (key.cullingLight->getType()) { case scene::LightType::SPHERE: { const auto* light = dynamic_cast(key.cullingLight); CC_ENSURES(light); - executeSphereLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + executeSphereLightCulling(*light, frustumCullingResult, lightBoundsCullingResult.instances); } break; case scene::LightType::SPOT: { const auto* light = dynamic_cast(key.cullingLight); CC_ENSURES(light); - executeSpotLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + executeSpotLightCulling(*light, frustumCullingResult, lightBoundsCullingResult.instances); } break; case scene::LightType::POINT: { const auto* light = dynamic_cast(key.cullingLight); CC_ENSURES(light); - executePointLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + executePointLightCulling(*light, frustumCullingResult, lightBoundsCullingResult.instances); } break; case scene::LightType::RANGED_DIRECTIONAL: { const auto* light = dynamic_cast(key.cullingLight); CC_ENSURES(light); - executeRangedDirectionalLightCulling(*light, frustumCullingResult, lightBoundsCullingResult); + executeRangedDirectionalLightCulling(*light, frustumCullingResult, lightBoundsCullingResult.instances); } break; case scene::LightType::DIRECTIONAL: case scene::LightType::UNKNOWN: @@ -585,7 +590,7 @@ void SceneCulling::fillRenderQueues( // is culled by light bounds if (lightBoundsCullingID.value != 0xFFFFFFFF) { CC_EXPECTS(lightBoundsCullingID.value < lightBoundsCullingResults.size()); - return lightBoundsCullingResults.at(lightBoundsCullingID.value); + return lightBoundsCullingResults.at(lightBoundsCullingID.value).instances; } // not culled by light bounds return frustumCullingResults.at(frustomCulledResultID.value); @@ -633,7 +638,8 @@ void SceneCulling::clear() noexcept { // light bounds culling lightBoundsCullings.clear(); for (auto& c : lightBoundsCullingResults) { - c.clear(); + c.instances.clear(); + c.lightByteOffset = 0xFFFFFFFF; } // native render queues for (auto& q : renderQueues) { @@ -650,6 +656,146 @@ void SceneCulling::clear() noexcept { numRenderQueues = 0; } +void LightResource::init(const NativeProgramLibrary& programLib, gfx::Device* deviceIn, uint32_t maxNumLightsIn) { + CC_EXPECTS(!device); + device = deviceIn; + programLibrary = &programLib; + + const auto& instanceLayout = programLibrary->localLayoutData; + const auto attrID = at(programLib.layoutGraph.attributeIndex, std::string_view{"CCForwardLight"}); + const auto& uniformBlock = instanceLayout.uniformBlocks.at(attrID); + + elementSize = boost::alignment::align_up( + getUniformBlockSize(uniformBlock.members), + device->getCapabilities().uboOffsetAlignment); + maxNumLights = maxNumLightsIn; + binding = programLib.localLayoutData.bindingMap.at(attrID); + + const auto bufferSize = elementSize * maxNumLights; + + lightBuffer = device->createBuffer(gfx::BufferInfo{ + gfx::BufferUsageBit::UNIFORM | gfx::BufferUsageBit::TRANSFER_DST, + gfx::MemoryUsageBit::HOST | gfx::MemoryUsageBit::DEVICE, + bufferSize, + elementSize, + }); + firstLightBufferView = device->createBuffer({lightBuffer, 0, elementSize}); + + cpuBuffer.resize(bufferSize); + lights.reserve(maxNumLights); + lightIndex.reserve(maxNumLights); + + CC_ENSURES(elementSize); + CC_ENSURES(maxNumLights); + + resized = true; +} + +uint32_t LightResource::addLight( + const scene::Light* light, + bool bHDR, + float exposure, + const scene::Shadows* shadowInfo) { + // already added + auto iter = lightIndex.find(light); + if (iter != lightIndex.end()) { + return iter->second; + } + + // resize buffer + if (lights.size() == maxNumLights) { + resized = true; + maxNumLights *= 2; + const auto bufferSize = elementSize * maxNumLights; + lightBuffer->resize(bufferSize); + firstLightBufferView = device->createBuffer({lightBuffer, 0, elementSize}); + cpuBuffer.resize(bufferSize); + lights.reserve(maxNumLights); + lightIndex.reserve(maxNumLights); + } + CC_ENSURES(lights.size() < maxNumLights); + + // add light + const auto lightID = static_cast(lights.size()); + lights.emplace_back(light); + auto res = lightIndex.emplace(light, lightID); + CC_ENSURES(res.second); + + // update buffer + const auto offset = elementSize * lightID; + setLightUBO(light, bHDR, exposure, shadowInfo, cpuBuffer.data() + offset, elementSize); + + return lightID * elementSize; +} + +void LightResource::buildLights( + SceneCulling& sceneCulling, + bool bHDR, + const scene::Shadows* shadowInfo) { + // build light buffer + for (const auto& [scene, lightBoundsCullings] : sceneCulling.lightBoundsCullings) { + for (const auto& [key, lightBoundsCullingID] : lightBoundsCullings.resultIndex) { + float exposure = 1.0F; + if (key.camera) { + exposure = key.camera->getExposure(); + } else if (key.probe && key.probe->getCamera()) { + exposure = key.probe->getCamera()->getExposure(); + } else { + CC_EXPECTS(false); + } + const auto lightByteOffset = addLight( + key.cullingLight, + bHDR, + exposure, + shadowInfo); + + // save light byte offset for each light bounds culling + auto& result = sceneCulling.lightBoundsCullingResults.at(lightBoundsCullingID.value); + result.lightByteOffset = lightByteOffset; + } + } + + // assign light byte offset to each queue + for (const auto& [sceneID, desc] : sceneCulling.renderQueueIndex) { + if (desc.lightBoundsCulledResultID.value == 0xFFFFFFFF) { + continue; + } + const auto lightByteOffset = sceneCulling.lightBoundsCullingResults.at( + desc.lightBoundsCulledResultID.value) + .lightByteOffset; + + sceneCulling.renderQueues.at(desc.renderQueueTarget.value).lightByteOffset = lightByteOffset; + } +} + +void LightResource::clear() { + std::fill(cpuBuffer.begin(), cpuBuffer.end(), 0); + lights.clear(); + lightIndex.clear(); +} + +void LightResource::buildLightBuffer(gfx::CommandBuffer* cmdBuffer) const { + cmdBuffer->updateBuffer(lightBuffer, cpuBuffer.data(), lights.size() * elementSize); +} + +void LightResource::tryUpdateRenderSceneLocalDescriptorSet(const SceneCulling& sceneCulling) { + if (!resized) { + return; + } + + for (const auto& [scene, culling] : sceneCulling.frustumCullings) { + for (const auto& model : scene->getModels()) { + CC_EXPECTS(model); + for (const auto& submodel : model->getSubModels()) { + auto* set = submodel->getDescriptorSet(); + set->bindBuffer(binding, firstLightBufferView); + set->update(); + } + } + } + resized = false; +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index b06cfbbc52b..e78cf4fb073 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -168,6 +168,7 @@ void NativeSetter::setBuiltinSphereLightConstants(const scene::SphereLight *ligh } void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) { + CC_EXPECTS(light); const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); const auto &shadowInfo = *sceneData.getShadows(); diff --git a/native/cocos/renderer/pipeline/custom/details/Map.h b/native/cocos/renderer/pipeline/custom/details/Map.h index a82d85a0472..ae6be1cc54d 100644 --- a/native/cocos/renderer/pipeline/custom/details/Map.h +++ b/native/cocos/renderer/pipeline/custom/details/Map.h @@ -106,6 +106,46 @@ using PmrUnorderedStringMultiMap = std::unordered_multimap< TransparentStringHash, std::equal_to<>, boost::container::pmr::polymorphic_allocator>>; +template +inline typename std::map, Allocator>::mapped_type& +at(std::map, Allocator>& m, const KeyLike& key) { + auto iter = m.find(key); + if (iter == m.end()) { + throw std::out_of_range("at(std::map) out of range"); + } + return iter->second; +} + +template +inline typename std::map, Allocator>::mapped_type const& +at(const std::map, Allocator>& m, const KeyLike& key) { + auto iter = m.find(key); + if (iter == m.end()) { + throw std::out_of_range("at(std::map) out of range"); + } + return iter->second; +} + +template +inline typename boost::container::flat_map, Allocator>::mapped_type& +at(boost::container::flat_map, Allocator>& m, const KeyLike& key) { + auto iter = m.find(key); + if (iter == m.end()) { + throw std::out_of_range("at(boost::container::flat_map) out of range"); + } + return iter->second; +} + +template +inline typename boost::container::flat_map, Allocator>::mapped_type const& +at(const boost::container::flat_map, Allocator>& m, const KeyLike& key) { + auto iter = m.find(key); + if (iter == m.end()) { + throw std::out_of_range("at(boost::container::flat_map) out of range"); + } + return iter->second; +} + } // namespace cc namespace ccstd { From 935443bbd542327d65ff015813a91b55ec2e178e Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 19 Sep 2023 19:06:28 +0800 Subject: [PATCH 63/82] revert change --- editor/assets/primitives.fbx.meta | 73 +++++++++++++++++++------------ 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/editor/assets/primitives.fbx.meta b/editor/assets/primitives.fbx.meta index cc3453b08e8..fdc6e41562b 100644 --- a/editor/assets/primitives.fbx.meta +++ b/editor/assets/primitives.fbx.meta @@ -19,8 +19,8 @@ ], "subMetas": {}, "userData": { - "gltfIndex": 4, - "triangleCount": 2380 + "gltfIndex": 5, + "triangleCount": 1512 } }, "801ec": { @@ -59,12 +59,12 @@ "triangleCount": 200 } }, - "38fd2": { + "40ece": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@40ece", "displayName": "", - "id": "38fd2", - "name": "cone.mesh", + "id": "40ece", + "name": "torus.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -74,15 +74,15 @@ "subMetas": {}, "userData": { "gltfIndex": 2, - "triangleCount": 72 + "triangleCount": 2048 } }, - "40ece": { + "fc873": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@40ece", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@fc873", "displayName": "", - "id": "40ece", - "name": "torus.mesh", + "id": "fc873", + "name": "quad.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -92,15 +92,15 @@ "subMetas": {}, "userData": { "gltfIndex": 3, - "triangleCount": 2048 + "triangleCount": 2 } }, - "fc873": { + "a804a": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@fc873", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", "displayName": "", - "id": "fc873", - "name": "quad.mesh", + "id": "a804a", + "name": "box.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -109,8 +109,8 @@ ], "subMetas": {}, "userData": { - "gltfIndex": 5, - "triangleCount": 2 + "gltfIndex": 4, + "triangleCount": 12 } }, "8abdc": { @@ -128,15 +128,15 @@ "subMetas": {}, "userData": { "gltfIndex": 6, - "triangleCount": 128 + "triangleCount": 112 } }, - "a804a": { + "38fd2": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", "displayName": "", - "id": "a804a", - "name": "box.mesh", + "id": "38fd2", + "name": "cone.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -146,9 +146,25 @@ "subMetas": {}, "userData": { "gltfIndex": 7, - "triangleCount": 12 + "triangleCount": 64 } }, + "7a3ca": { + "importer": "gltf-material", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@7a3ca", + "displayName": "", + "id": "7a3ca", + "name": "lambert2.material", + "userData": { + "gltfIndex": 0 + }, + "ver": "1.0.14", + "imported": true, + "files": [ + ".json" + ], + "subMetas": {} + }, "8d883": { "importer": "gltf-material", "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@8d883", @@ -156,7 +172,7 @@ "id": "8d883", "name": "lambert1.material", "userData": { - "gltfIndex": 0 + "gltfIndex": 1 }, "ver": "1.0.14", "imported": true, @@ -203,14 +219,15 @@ "meshes": [ "1263d74c-8167-4928-91a6-4e2672411f47@801ec", "1263d74c-8167-4928-91a6-4e2672411f47@2e76e", - "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", "1263d74c-8167-4928-91a6-4e2672411f47@40ece", - "1263d74c-8167-4928-91a6-4e2672411f47@17020", "1263d74c-8167-4928-91a6-4e2672411f47@fc873", + "1263d74c-8167-4928-91a6-4e2672411f47@a804a", + "1263d74c-8167-4928-91a6-4e2672411f47@17020", "1263d74c-8167-4928-91a6-4e2672411f47@8abdc", - "1263d74c-8167-4928-91a6-4e2672411f47@a804a" + "1263d74c-8167-4928-91a6-4e2672411f47@38fd2" ], "materials": [ + "1263d74c-8167-4928-91a6-4e2672411f47@7a3ca", "1263d74c-8167-4928-91a6-4e2672411f47@8d883" ], "scenes": [ From 92be04462c8fc00578c097bd767720b81143fab2 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 20 Sep 2023 11:12:23 +0800 Subject: [PATCH 64/82] lint --- cocos/rendering/custom/pipeline.ts | 34 +++++++++---------- .../pipeline/custom/NativePipelineTypes.h | 8 ++--- .../pipeline/custom/NativeSceneCulling.cpp | 5 ++- .../pipeline/custom/RenderInterfaceTypes.h | 8 ++--- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 4005d5eac9d..e97d787ff1f 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -685,9 +685,20 @@ export interface BasicPipeline extends PipelineRuntime { width: number, height: number, format?: Format): void; - addResource ( + addBuffer ( name: string, - dimension: ResourceDimension, + size: number, + flags: ResourceFlags, + residency: ResourceResidency): number; + updateBuffer (name: string, size: number): void; + addExternalTexture ( + name: string, + texture: Texture, + flags: ResourceFlags): number; + updateExternalTexture (name: string, texture: Texture): void; + addTexture ( + name: string, + type: TextureType, format: Format, width: number, height: number, @@ -697,7 +708,7 @@ export interface BasicPipeline extends PipelineRuntime { sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number; - updateResource ( + updateTexture ( name: string, format: Format, width: number, @@ -706,9 +717,9 @@ export interface BasicPipeline extends PipelineRuntime { arraySize: number, mipLevels: number, sampleCount: SampleCount): void; - addTexture ( + addResource ( name: string, - type: TextureType, + dimension: ResourceDimension, format: Format, width: number, height: number, @@ -718,7 +729,7 @@ export interface BasicPipeline extends PipelineRuntime { sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number; - updateTexture ( + updateResource ( name: string, format: Format, width: number, @@ -727,17 +738,6 @@ export interface BasicPipeline extends PipelineRuntime { arraySize: number, mipLevels: number, sampleCount: SampleCount): void; - addBuffer ( - name: string, - size: number, - flags: ResourceFlags, - residency: ResourceResidency): number; - updateBuffer (name: string, size: number): void; - addExternalTexture ( - name: string, - texture: Texture, - flags: ResourceFlags): number; - updateExternalTexture (name: string, texture: Texture): void; /** * @engineInternal * @en Begin rendering one frame diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index c17bd4871b5..c6c1cbb9c1f 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1621,14 +1621,14 @@ class NativePipeline final : public Pipeline { uint32_t addDepthStencil(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, ResourceResidency residency) override; void updateRenderTarget(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) override; void updateDepthStencil(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) override; - uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; - void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; - uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; - void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; uint32_t addBuffer(const ccstd::string &name, uint32_t size, ResourceFlags flags, ResourceResidency residency) override; void updateBuffer(const ccstd::string &name, uint32_t size) override; uint32_t addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) override; void updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) override; + uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; + void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; + uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; + void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; void beginFrame() override; void update(const scene::Camera *camera) override; void endFrame() override; diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index cc805461604..36e43830185 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -775,7 +775,10 @@ void LightResource::clear() { } void LightResource::buildLightBuffer(gfx::CommandBuffer* cmdBuffer) const { - cmdBuffer->updateBuffer(lightBuffer, cpuBuffer.data(), lights.size() * elementSize); + cmdBuffer->updateBuffer( + lightBuffer, + cpuBuffer.data(), + static_cast(lights.size()) * elementSize); } void LightResource::tryUpdateRenderSceneLocalDescriptorSet(const SceneCulling& sceneCulling) { diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 0e0ea222191..dfa2210c52b 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -786,14 +786,14 @@ class BasicPipeline : public PipelineRuntime { * @param format @en Format of the resource @zh 资源的格式 */ virtual void updateDepthStencil(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) = 0; - virtual uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) = 0; - virtual void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) = 0; - virtual uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) = 0; - virtual void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) = 0; virtual uint32_t addBuffer(const ccstd::string &name, uint32_t size, ResourceFlags flags, ResourceResidency residency) = 0; virtual void updateBuffer(const ccstd::string &name, uint32_t size) = 0; virtual uint32_t addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) = 0; virtual void updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) = 0; + virtual uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) = 0; + virtual void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) = 0; + virtual uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) = 0; + virtual void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) = 0; /** * @engineInternal * @en Begin rendering one frame From 4d9d3928c27f7e56c8df8bbb61abe1cf1b2a8807 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 20 Sep 2023 15:22:14 +0800 Subject: [PATCH 65/82] add profile marker --- native/cocos/renderer/pipeline/custom/NativeExecutor.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 78c45082cb6..6ac1c309012 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -2022,6 +2022,10 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { // upload buffers { + auto& ctx = ppl.nativeContext; +#if CC_DEBUG + submit.primaryCommandBuffer->beginMarker(makeMarkerInfo("Internal Upload", RASTER_UPLOAD_COLOR)); +#endif // scene const auto& sceneCulling = ppl.nativeContext.sceneCulling; for (uint32_t queueID = 0; queueID != sceneCulling.numRenderQueues; ++queueID) { @@ -2033,9 +2037,11 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { } // lights - auto& ctx = ppl.nativeContext; ctx.lightResources.buildLightBuffer(submit.primaryCommandBuffer); ctx.lightResources.tryUpdateRenderSceneLocalDescriptorSet(sceneCulling); +#if CC_DEBUG + submit.primaryCommandBuffer->endMarker(); +#endif } ccstd::pmr::unordered_map< From f27a99cb134c17525c3d590bce85a9004bcffd99 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 20 Sep 2023 16:57:17 +0800 Subject: [PATCH 66/82] add debug object pool --- cocos/rendering/custom/layout-graph.ts | 127 ++++++++++++-- cocos/rendering/custom/render-graph.ts | 232 +++++++++++++++++++++---- cocos/rendering/custom/types.ts | 71 ++++++-- 3 files changed, 369 insertions(+), 61 deletions(-) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 4e8d25991dd..3accaa29592 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -1420,17 +1420,32 @@ export class LayoutGraphObjectPool { this._layoutGraphData.reset(); } createDescriptorDB (): DescriptorDB { - const v = this._descriptorDB.add(); + let v: DescriptorDB; + if (this.debug) { + v = new DescriptorDB(); + } else { + v = this._descriptorDB.add(); + } v.reset(); return v; } createRenderPhase (): RenderPhase { - const v = this._renderPhase.add(); + let v: RenderPhase; + if (this.debug) { + v = new RenderPhase(); + } else { + v = this._renderPhase.add(); + } v.reset(); return v; } createLayoutGraph (): LayoutGraph { - const v = this._layoutGraph.add(); + let v: LayoutGraph; + if (this.debug) { + v = new LayoutGraph(); + } else { + v = this._layoutGraph.add(); + } v.clear(); return v; } @@ -1439,12 +1454,22 @@ export class LayoutGraphObjectPool { uniformType: Type = Type.UNKNOWN, offset = 0, ): UniformData { - const v = this._uniformData.add(); + let v: UniformData; + if (this.debug) { + v = new UniformData(); + } else { + v = this._uniformData.add(); + } v.reset(uniformID, uniformType, offset); return v; } createUniformBlockData (): UniformBlockData { - const v = this._uniformBlockData.add(); + let v: UniformBlockData; + if (this.debug) { + v = new UniformBlockData(); + } else { + v = this._uniformBlockData.add(); + } v.reset(); return v; } @@ -1453,7 +1478,12 @@ export class LayoutGraphObjectPool { type: Type = Type.UNKNOWN, count = 1, ): DescriptorData { - const v = this._descriptorData.add(); + let v: DescriptorData; + if (this.debug) { + v = new DescriptorData(); + } else { + v = this._descriptorData.add(); + } v.reset(descriptorID, type, count); return v; } @@ -1462,7 +1492,12 @@ export class LayoutGraphObjectPool { visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, capacity = 0, ): DescriptorBlockData { - const v = this._descriptorBlockData.add(); + let v: DescriptorBlockData; + if (this.debug) { + v = new DescriptorBlockData(); + } else { + v = this._descriptorBlockData.add(); + } v.reset(type, visibility, capacity); return v; } @@ -1470,7 +1505,12 @@ export class LayoutGraphObjectPool { slot = 0xFFFFFFFF, capacity = 0, ): DescriptorSetLayoutData { - const v = this._descriptorSetLayoutData.add(); + let v: DescriptorSetLayoutData; + if (this.debug) { + v = new DescriptorSetLayoutData(); + } else { + v = this._descriptorSetLayoutData.add(); + } v.reset(slot, capacity); return v; } @@ -1478,52 +1518,102 @@ export class LayoutGraphObjectPool { descriptorSetLayout: DescriptorSetLayout | null = null, descriptorSet: DescriptorSet | null = null, ): DescriptorSetData { - const v = this._descriptorSetData.add(); + let v: DescriptorSetData; + if (this.debug) { + v = new DescriptorSetData(); + } else { + v = this._descriptorSetData.add(); + } v.reset(descriptorSetLayout, descriptorSet); return v; } createPipelineLayoutData (): PipelineLayoutData { - const v = this._pipelineLayoutData.add(); + let v: PipelineLayoutData; + if (this.debug) { + v = new PipelineLayoutData(); + } else { + v = this._pipelineLayoutData.add(); + } v.reset(); return v; } createShaderBindingData (): ShaderBindingData { - const v = this._shaderBindingData.add(); + let v: ShaderBindingData; + if (this.debug) { + v = new ShaderBindingData(); + } else { + v = this._shaderBindingData.add(); + } v.reset(); return v; } createShaderLayoutData (): ShaderLayoutData { - const v = this._shaderLayoutData.add(); + let v: ShaderLayoutData; + if (this.debug) { + v = new ShaderLayoutData(); + } else { + v = this._shaderLayoutData.add(); + } v.reset(); return v; } createTechniqueData (): TechniqueData { - const v = this._techniqueData.add(); + let v: TechniqueData; + if (this.debug) { + v = new TechniqueData(); + } else { + v = this._techniqueData.add(); + } v.reset(); return v; } createEffectData (): EffectData { - const v = this._effectData.add(); + let v: EffectData; + if (this.debug) { + v = new EffectData(); + } else { + v = this._effectData.add(); + } v.reset(); return v; } createShaderProgramData (): ShaderProgramData { - const v = this._shaderProgramData.add(); + let v: ShaderProgramData; + if (this.debug) { + v = new ShaderProgramData(); + } else { + v = this._shaderProgramData.add(); + } v.reset(); return v; } createRenderStageData (): RenderStageData { - const v = this._renderStageData.add(); + let v: RenderStageData; + if (this.debug) { + v = new RenderStageData(); + } else { + v = this._renderStageData.add(); + } v.reset(); return v; } createRenderPhaseData (): RenderPhaseData { - const v = this._renderPhaseData.add(); + let v: RenderPhaseData; + if (this.debug) { + v = new RenderPhaseData(); + } else { + v = this._renderPhaseData.add(); + } v.reset(); return v; } createLayoutGraphData (): LayoutGraphData { - const v = this._layoutGraphData.add(); + let v: LayoutGraphData; + if (this.debug) { + v = new LayoutGraphData(); + } else { + v = this._layoutGraphData.add(); + } v.clear(); return v; } @@ -1546,6 +1636,7 @@ export class LayoutGraphObjectPool { private readonly _renderStageData: RecyclePool; private readonly _renderPhaseData: RecyclePool; private readonly _layoutGraphData: RecyclePool; + public debug = false; } export function saveDescriptorDB (ar: OutputArchive, v: DescriptorDB): void { diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 135d22cd640..abf231b2ab9 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -2665,7 +2665,12 @@ export class RenderGraphObjectPool { z = 0, w = 0, ): ClearValue { - const v = this._clearValue.add(); + let v: ClearValue; + if (this.debug) { + v = new ClearValue(); + } else { + v = this._clearValue.add(); + } v.reset(x, y, z, w); return v; } @@ -2678,7 +2683,12 @@ export class RenderGraphObjectPool { clearFlags: ClearFlagBit = ClearFlagBit.ALL, shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, ): RasterView { - const v = this._rasterView.add(); + let v: RasterView; + if (this.debug) { + v = new RasterView(); + } else { + v = this._rasterView.add(); + } v.reset(slotName, accessType, attachmentType, loadOp, storeOp, clearFlags, shaderStageFlags); return v; } @@ -2689,74 +2699,134 @@ export class RenderGraphObjectPool { clearValueType: ClearValueType = ClearValueType.NONE, shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, ): ComputeView { - const v = this._computeView.add(); + let v: ComputeView; + if (this.debug) { + v = new ComputeView(); + } else { + v = this._computeView.add(); + } v.reset(name, accessType, clearFlags, clearValueType, shaderStageFlags); return v; } createResourceDesc (): ResourceDesc { - const v = this._resourceDesc.add(); + let v: ResourceDesc; + if (this.debug) { + v = new ResourceDesc(); + } else { + v = this._resourceDesc.add(); + } v.reset(); return v; } createResourceTraits ( residency: ResourceResidency = ResourceResidency.MANAGED, ): ResourceTraits { - const v = this._resourceTraits.add(); + let v: ResourceTraits; + if (this.debug) { + v = new ResourceTraits(); + } else { + v = this._resourceTraits.add(); + } v.reset(residency); return v; } createRenderSwapchain ( swapchain: Swapchain | null = null, ): RenderSwapchain { - const v = this._renderSwapchain.add(); + let v: RenderSwapchain; + if (this.debug) { + v = new RenderSwapchain(); + } else { + v = this._renderSwapchain.add(); + } v.reset(swapchain); return v; } createResourceStates (): ResourceStates { - const v = this._resourceStates.add(); + let v: ResourceStates; + if (this.debug) { + v = new ResourceStates(); + } else { + v = this._resourceStates.add(); + } v.reset(); return v; } createManagedBuffer ( buffer: Buffer | null = null, ): ManagedBuffer { - const v = this._managedBuffer.add(); + let v: ManagedBuffer; + if (this.debug) { + v = new ManagedBuffer(); + } else { + v = this._managedBuffer.add(); + } v.reset(buffer); return v; } createPersistentBuffer ( buffer: Buffer | null = null, ): PersistentBuffer { - const v = this._persistentBuffer.add(); + let v: PersistentBuffer; + if (this.debug) { + v = new PersistentBuffer(); + } else { + v = this._persistentBuffer.add(); + } v.reset(buffer); return v; } createManagedTexture ( texture: Texture | null = null, ): ManagedTexture { - const v = this._managedTexture.add(); + let v: ManagedTexture; + if (this.debug) { + v = new ManagedTexture(); + } else { + v = this._managedTexture.add(); + } v.reset(texture); return v; } createPersistentTexture ( texture: Texture | null = null, ): PersistentTexture { - const v = this._persistentTexture.add(); + let v: PersistentTexture; + if (this.debug) { + v = new PersistentTexture(); + } else { + v = this._persistentTexture.add(); + } v.reset(texture); return v; } createManagedResource (): ManagedResource { - const v = this._managedResource.add(); + let v: ManagedResource; + if (this.debug) { + v = new ManagedResource(); + } else { + v = this._managedResource.add(); + } v.reset(); return v; } createSubpass (): Subpass { - const v = this._subpass.add(); + let v: Subpass; + if (this.debug) { + v = new Subpass(); + } else { + v = this._subpass.add(); + } v.reset(); return v; } createSubpassGraph (): SubpassGraph { - const v = this._subpassGraph.add(); + let v: SubpassGraph; + if (this.debug) { + v = new SubpassGraph(); + } else { + v = this._subpassGraph.add(); + } v.clear(); return v; } @@ -2765,19 +2835,34 @@ export class RenderGraphObjectPool { count = 1, quality = 0, ): RasterSubpass { - const v = this._rasterSubpass.add(); + let v: RasterSubpass; + if (this.debug) { + v = new RasterSubpass(); + } else { + v = this._rasterSubpass.add(); + } v.reset(subpassID, count, quality); return v; } createComputeSubpass ( subpassID = 0xFFFFFFFF, ): ComputeSubpass { - const v = this._computeSubpass.add(); + let v: ComputeSubpass; + if (this.debug) { + v = new ComputeSubpass(); + } else { + v = this._computeSubpass.add(); + } v.reset(subpassID); return v; } createRasterPass (): RasterPass { - const v = this._rasterPass.add(); + let v: RasterPass; + if (this.debug) { + v = new RasterPass(); + } else { + v = this._rasterPass.add(); + } v.reset(); return v; } @@ -2785,47 +2870,92 @@ export class RenderGraphObjectPool { renderPass: RenderPass | null = null, framebuffer: Framebuffer | null = null, ): PersistentRenderPassAndFramebuffer { - const v = this._persistentRenderPassAndFramebuffer.add(); + let v: PersistentRenderPassAndFramebuffer; + if (this.debug) { + v = new PersistentRenderPassAndFramebuffer(); + } else { + v = this._persistentRenderPassAndFramebuffer.add(); + } v.reset(renderPass, framebuffer); return v; } createFormatView (): FormatView { - const v = this._formatView.add(); + let v: FormatView; + if (this.debug) { + v = new FormatView(); + } else { + v = this._formatView.add(); + } v.reset(); return v; } createSubresourceView (): SubresourceView { - const v = this._subresourceView.add(); + let v: SubresourceView; + if (this.debug) { + v = new SubresourceView(); + } else { + v = this._subresourceView.add(); + } v.reset(); return v; } createResourceGraph (): ResourceGraph { - const v = this._resourceGraph.add(); + let v: ResourceGraph; + if (this.debug) { + v = new ResourceGraph(); + } else { + v = this._resourceGraph.add(); + } v.clear(); return v; } createComputePass (): ComputePass { - const v = this._computePass.add(); + let v: ComputePass; + if (this.debug) { + v = new ComputePass(); + } else { + v = this._computePass.add(); + } v.reset(); return v; } createResolvePass (): ResolvePass { - const v = this._resolvePass.add(); + let v: ResolvePass; + if (this.debug) { + v = new ResolvePass(); + } else { + v = this._resolvePass.add(); + } v.reset(); return v; } createCopyPass (): CopyPass { - const v = this._copyPass.add(); + let v: CopyPass; + if (this.debug) { + v = new CopyPass(); + } else { + v = this._copyPass.add(); + } v.reset(); return v; } createMovePass (): MovePass { - const v = this._movePass.add(); + let v: MovePass; + if (this.debug) { + v = new MovePass(); + } else { + v = this._movePass.add(); + } v.reset(); return v; } createRaytracePass (): RaytracePass { - const v = this._raytracePass.add(); + let v: RaytracePass; + if (this.debug) { + v = new RaytracePass(); + } else { + v = this._raytracePass.add(); + } v.reset(); return v; } @@ -2833,7 +2963,12 @@ export class RenderGraphObjectPool { slotName = '', clearFlags: ClearFlagBit = ClearFlagBit.ALL, ): ClearView { - const v = this._clearView.add(); + let v: ClearView; + if (this.debug) { + v = new ClearView(); + } else { + v = this._clearView.add(); + } v.reset(slotName, clearFlags); return v; } @@ -2841,7 +2976,12 @@ export class RenderGraphObjectPool { hint: QueueHint = QueueHint.RENDER_OPAQUE, phaseID = 0xFFFFFFFF, ): RenderQueue { - const v = this._renderQueue.add(); + let v: RenderQueue; + if (this.debug) { + v = new RenderQueue(); + } else { + v = this._renderQueue.add(); + } v.reset(hint, phaseID); return v; } @@ -2852,7 +2992,12 @@ export class RenderGraphObjectPool { cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, shadingLight: Light | null = null, ): SceneData { - const v = this._sceneData.add(); + let v: SceneData; + if (this.debug) { + v = new SceneData(); + } else { + v = this._sceneData.add(); + } v.reset(scene, camera, flags, cullingFlags, shadingLight); return v; } @@ -2863,7 +3008,12 @@ export class RenderGraphObjectPool { threadGroupCountY = 0, threadGroupCountZ = 0, ): Dispatch { - const v = this._dispatch.add(); + let v: Dispatch; + if (this.debug) { + v = new Dispatch(); + } else { + v = this._dispatch.add(); + } v.reset(material, passID, threadGroupCountX, threadGroupCountY, threadGroupCountZ); return v; } @@ -2873,17 +3023,32 @@ export class RenderGraphObjectPool { sceneFlags: SceneFlags = SceneFlags.NONE, camera: Camera | null = null, ): Blit { - const v = this._blit.add(); + let v: Blit; + if (this.debug) { + v = new Blit(); + } else { + v = this._blit.add(); + } v.reset(material, passID, sceneFlags, camera); return v; } createRenderData (): RenderData { - const v = this._renderData.add(); + let v: RenderData; + if (this.debug) { + v = new RenderData(); + } else { + v = this._renderData.add(); + } v.reset(); return v; } createRenderGraph (): RenderGraph { - const v = this._renderGraph.add(); + let v: RenderGraph; + if (this.debug) { + v = new RenderGraph(); + } else { + v = this._renderGraph.add(); + } v.clear(); return v; } @@ -2921,4 +3086,5 @@ export class RenderGraphObjectPool { private readonly _blit: RecyclePool; private readonly _renderData: RecyclePool; private readonly _renderGraph: RecyclePool; + public debug = false; } diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 577955e8017..f098a245129 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -671,24 +671,44 @@ export class RenderCommonObjectPool { culledByLight = false, probe: ReflectionProbe | null = null, ): LightInfo { - const v = this._lightInfo.add(); + let v: LightInfo; + if (this.debug) { + v = new LightInfo(); + } else { + v = this._lightInfo.add(); + } v.reset(light, level, culledByLight, probe); return v; } createDescriptor ( type: Type = Type.UNKNOWN, ): Descriptor { - const v = this._descriptor.add(); + let v: Descriptor; + if (this.debug) { + v = new Descriptor(); + } else { + v = this._descriptor.add(); + } v.reset(type); return v; } createDescriptorBlock (): DescriptorBlock { - const v = this._descriptorBlock.add(); + let v: DescriptorBlock; + if (this.debug) { + v = new DescriptorBlock(); + } else { + v = this._descriptorBlock.add(); + } v.reset(); return v; } createDescriptorBlockFlattened (): DescriptorBlockFlattened { - const v = this._descriptorBlockFlattened.add(); + let v: DescriptorBlockFlattened; + if (this.debug) { + v = new DescriptorBlockFlattened(); + } else { + v = this._descriptorBlockFlattened.add(); + } v.reset(); return v; } @@ -698,7 +718,12 @@ export class RenderCommonObjectPool { descriptorType: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, ): DescriptorBlockIndex { - const v = this._descriptorBlockIndex.add(); + let v: DescriptorBlockIndex; + if (this.debug) { + v = new DescriptorBlockIndex(); + } else { + v = this._descriptorBlockIndex.add(); + } v.updateFrequency = updateFrequency; v.parameterType = parameterType; v.descriptorType = descriptorType; @@ -712,7 +737,12 @@ export class RenderCommonObjectPool { mode: ResolveMode = ResolveMode.SAMPLE_ZERO, mode1: ResolveMode = ResolveMode.SAMPLE_ZERO, ): ResolvePair { - const v = this._resolvePair.add(); + let v: ResolvePair; + if (this.debug) { + v = new ResolvePair(); + } else { + v = this._resolvePair.add(); + } v.reset(source, target, resolveFlags, mode, mode1); return v; } @@ -728,7 +758,12 @@ export class RenderCommonObjectPool { targetFirstSlice = 0, targetPlaneSlice = 0, ): CopyPair { - const v = this._copyPair.add(); + let v: CopyPair; + if (this.debug) { + v = new CopyPair(); + } else { + v = this._copyPair.add(); + } v.reset(source, target, mipLevels, numSlices, sourceMostDetailedMip, sourceFirstSlice, sourcePlaneSlice, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } @@ -740,7 +775,12 @@ export class RenderCommonObjectPool { targetFirstSlice = 0, targetPlaneSlice = 0, ): UploadPair { - const v = this._uploadPair.add(); + let v: UploadPair; + if (this.debug) { + v = new UploadPair(); + } else { + v = this._uploadPair.add(); + } v.reset(target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } @@ -753,12 +793,22 @@ export class RenderCommonObjectPool { targetFirstSlice = 0, targetPlaneSlice = 0, ): MovePair { - const v = this._movePair.add(); + let v: MovePair; + if (this.debug) { + v = new MovePair(); + } else { + v = this._movePair.add(); + } v.reset(source, target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } createPipelineStatistics (): PipelineStatistics { - const v = this._pipelineStatistics.add(); + let v: PipelineStatistics; + if (this.debug) { + v = new PipelineStatistics(); + } else { + v = this._pipelineStatistics.add(); + } v.reset(); return v; } @@ -772,6 +822,7 @@ export class RenderCommonObjectPool { private readonly _uploadPair: RecyclePool; private readonly _movePair: RecyclePool; private readonly _pipelineStatistics: RecyclePool; + public debug = false; } export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { From 5b44fcd5ab0c1acdbd70f12263a39ac0d1aba9af Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 20 Sep 2023 17:22:18 +0800 Subject: [PATCH 67/82] add object pool tracking --- cocos/rendering/custom/archive.ts | 2 + cocos/rendering/custom/layout-graph.ts | 36 ++++++++++++++ cocos/rendering/custom/pipeline.ts | 19 ++++++++ cocos/rendering/custom/private.ts | 2 + cocos/rendering/custom/render-graph.ts | 66 ++++++++++++++++++++++++++ cocos/rendering/custom/types.ts | 20 ++++++++ cocos/rendering/custom/web-types.ts | 2 + 7 files changed, 147 insertions(+) diff --git a/cocos/rendering/custom/archive.ts b/cocos/rendering/custom/archive.ts index 9b513ffc2bd..3d1ea4859c7 100644 --- a/cocos/rendering/custom/archive.ts +++ b/cocos/rendering/custom/archive.ts @@ -32,10 +32,12 @@ export interface OutputArchive { writeBool (value: boolean): void; writeNumber (value: number): void; writeString (value: string): void; + _pool?: boolean; } export interface InputArchive { readBool (): boolean; readNumber (): number; readString (): string; + _pool?: boolean; } diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 3accaa29592..b50bc99c0a1 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -40,6 +40,7 @@ export class DescriptorDB { this.blocks.clear(); } readonly blocks: Map = new Map(); + _pool?: boolean; } export class RenderPhase { @@ -47,6 +48,7 @@ export class RenderPhase { this.shaders.clear(); } readonly shaders: Set = new Set(); + _pool?: boolean; } export enum RenderPassType { @@ -586,6 +588,7 @@ export class LayoutGraph implements BidirectionalGraph readonly _vertices: LayoutGraphVertex[] = []; readonly _names: string[] = []; readonly _descriptors: DescriptorDB[] = []; + _pool?: boolean; } export class UniformData { @@ -604,6 +607,7 @@ export class UniformData { uniformType: Type; offset: number; size = 0; + _pool?: boolean; } export class UniformBlockData { @@ -613,6 +617,7 @@ export class UniformBlockData { } bufferSize = 0; readonly uniforms: UniformData[] = []; + _pool?: boolean; } export class DescriptorData { @@ -629,6 +634,7 @@ export class DescriptorData { descriptorID: number; type: Type; count: number; + _pool?: boolean; } export class DescriptorBlockData { @@ -649,6 +655,7 @@ export class DescriptorBlockData { offset = 0; capacity: number; readonly descriptors: DescriptorData[] = []; + _pool?: boolean; } export class DescriptorSetLayoutData { @@ -684,6 +691,7 @@ export class DescriptorSetLayoutData { readonly descriptorBlocks: DescriptorBlockData[]; readonly uniformBlocks: Map; readonly bindingMap: Map; + _pool?: boolean; } export class DescriptorSetData { @@ -702,6 +710,7 @@ export class DescriptorSetData { readonly descriptorSetLayoutInfo: DescriptorSetLayoutInfo = new DescriptorSetLayoutInfo(); /*refcount*/ descriptorSetLayout: DescriptorSetLayout | null; /*refcount*/ descriptorSet: DescriptorSet | null; + _pool?: boolean; } export class PipelineLayoutData { @@ -709,6 +718,7 @@ export class PipelineLayoutData { this.descriptorSets.clear(); } readonly descriptorSets: Map = new Map(); + _pool?: boolean; } export class ShaderBindingData { @@ -716,6 +726,7 @@ export class ShaderBindingData { this.descriptorBindings.clear(); } readonly descriptorBindings: Map = new Map(); + _pool?: boolean; } export class ShaderLayoutData { @@ -725,6 +736,7 @@ export class ShaderLayoutData { } readonly layoutData: Map = new Map(); readonly bindingData: Map = new Map(); + _pool?: boolean; } export class TechniqueData { @@ -732,6 +744,7 @@ export class TechniqueData { this.passes.length = 0; } readonly passes: ShaderLayoutData[] = []; + _pool?: boolean; } export class EffectData { @@ -739,6 +752,7 @@ export class EffectData { this.techniques.clear(); } readonly techniques: Map = new Map(); + _pool?: boolean; } export class ShaderProgramData { @@ -748,6 +762,7 @@ export class ShaderProgramData { } readonly layout: PipelineLayoutData = new PipelineLayoutData(); /*refcount*/ pipelineLayout: PipelineLayout | null = null; + _pool?: boolean; } export class RenderStageData { @@ -755,6 +770,7 @@ export class RenderStageData { this.descriptorVisibility.clear(); } readonly descriptorVisibility: Map = new Map(); + _pool?: boolean; } export class RenderPhaseData { @@ -768,6 +784,7 @@ export class RenderPhaseData { readonly shaderPrograms: ShaderProgramData[] = []; readonly shaderIndex: Map = new Map(); /*refcount*/ pipelineLayout: PipelineLayout | null = null; + _pool?: boolean; } //================================================================= @@ -1334,6 +1351,7 @@ export class LayoutGraphData implements BidirectionalGraph readonly shaderLayoutIndex: Map = new Map(); readonly effects: Map = new Map(); constantMacros = ''; + _pool?: boolean; } export class LayoutGraphObjectPoolSettings { @@ -1425,6 +1443,7 @@ export class LayoutGraphObjectPool { v = new DescriptorDB(); } else { v = this._descriptorDB.add(); + v._pool = true; } v.reset(); return v; @@ -1435,6 +1454,7 @@ export class LayoutGraphObjectPool { v = new RenderPhase(); } else { v = this._renderPhase.add(); + v._pool = true; } v.reset(); return v; @@ -1445,6 +1465,7 @@ export class LayoutGraphObjectPool { v = new LayoutGraph(); } else { v = this._layoutGraph.add(); + v._pool = true; } v.clear(); return v; @@ -1459,6 +1480,7 @@ export class LayoutGraphObjectPool { v = new UniformData(); } else { v = this._uniformData.add(); + v._pool = true; } v.reset(uniformID, uniformType, offset); return v; @@ -1469,6 +1491,7 @@ export class LayoutGraphObjectPool { v = new UniformBlockData(); } else { v = this._uniformBlockData.add(); + v._pool = true; } v.reset(); return v; @@ -1483,6 +1506,7 @@ export class LayoutGraphObjectPool { v = new DescriptorData(); } else { v = this._descriptorData.add(); + v._pool = true; } v.reset(descriptorID, type, count); return v; @@ -1497,6 +1521,7 @@ export class LayoutGraphObjectPool { v = new DescriptorBlockData(); } else { v = this._descriptorBlockData.add(); + v._pool = true; } v.reset(type, visibility, capacity); return v; @@ -1510,6 +1535,7 @@ export class LayoutGraphObjectPool { v = new DescriptorSetLayoutData(); } else { v = this._descriptorSetLayoutData.add(); + v._pool = true; } v.reset(slot, capacity); return v; @@ -1523,6 +1549,7 @@ export class LayoutGraphObjectPool { v = new DescriptorSetData(); } else { v = this._descriptorSetData.add(); + v._pool = true; } v.reset(descriptorSetLayout, descriptorSet); return v; @@ -1533,6 +1560,7 @@ export class LayoutGraphObjectPool { v = new PipelineLayoutData(); } else { v = this._pipelineLayoutData.add(); + v._pool = true; } v.reset(); return v; @@ -1543,6 +1571,7 @@ export class LayoutGraphObjectPool { v = new ShaderBindingData(); } else { v = this._shaderBindingData.add(); + v._pool = true; } v.reset(); return v; @@ -1553,6 +1582,7 @@ export class LayoutGraphObjectPool { v = new ShaderLayoutData(); } else { v = this._shaderLayoutData.add(); + v._pool = true; } v.reset(); return v; @@ -1563,6 +1593,7 @@ export class LayoutGraphObjectPool { v = new TechniqueData(); } else { v = this._techniqueData.add(); + v._pool = true; } v.reset(); return v; @@ -1573,6 +1604,7 @@ export class LayoutGraphObjectPool { v = new EffectData(); } else { v = this._effectData.add(); + v._pool = true; } v.reset(); return v; @@ -1583,6 +1615,7 @@ export class LayoutGraphObjectPool { v = new ShaderProgramData(); } else { v = this._shaderProgramData.add(); + v._pool = true; } v.reset(); return v; @@ -1593,6 +1626,7 @@ export class LayoutGraphObjectPool { v = new RenderStageData(); } else { v = this._renderStageData.add(); + v._pool = true; } v.reset(); return v; @@ -1603,6 +1637,7 @@ export class LayoutGraphObjectPool { v = new RenderPhaseData(); } else { v = this._renderPhaseData.add(); + v._pool = true; } v.reset(); return v; @@ -1613,6 +1648,7 @@ export class LayoutGraphObjectPool { v = new LayoutGraphData(); } else { v = this._layoutGraphData.add(); + v._pool = true; } v.clear(); return v; diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index e97d787ff1f..0dcb547d86a 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -179,6 +179,7 @@ export interface PipelineRuntime { * @zh 触发管线状态更新事件 */ onGlobalPipelineStateChanged (): void; + _pool?: boolean; } /** @@ -268,6 +269,7 @@ export enum SubpassCapabilities { */ export class PipelineCapabilities { subpass: SubpassCapabilities = SubpassCapabilities.NONE; + _pool?: boolean; } /** @@ -286,6 +288,7 @@ export interface RenderNode { * @experimental */ setCustomBehavior (name: string): void; + _pool?: boolean; } /** @@ -390,6 +393,7 @@ export interface Setter extends RenderNode { light: DirectionalLight, csmLevel?: number): void; setBuiltinSpotLightFrustumConstants (light: SpotLight): void; + _pool?: boolean; } export interface SceneBuilder extends Setter { @@ -397,6 +401,7 @@ export interface SceneBuilder extends Setter { light: Light, csmLevel?: number, optCamera?: Camera): void; + _pool?: boolean; } /** @@ -465,6 +470,7 @@ export interface RenderQueueBuilder extends Setter { * @experimental */ addCustomCommand (customBehavior: string): void; + _pool?: boolean; } /** @@ -559,6 +565,7 @@ export interface BasicRenderPassBuilder extends Setter { * @zh 在屏幕上渲染统计数据 */ showStatistics: boolean; + _pool?: boolean; } export interface BasicMultisampleRenderPassBuilder extends BasicRenderPassBuilder { @@ -568,6 +575,7 @@ export interface BasicMultisampleRenderPassBuilder extends BasicRenderPassBuilde target: string, depthMode?: ResolveMode, stencilMode?: ResolveMode): void; + _pool?: boolean; } /** @@ -816,6 +824,7 @@ export interface BasicPipeline extends PipelineRuntime { * @engineInternal */ getDescriptorSetLayout (shaderName: string, freq: UpdateFrequency): DescriptorSetLayout | undefined; + _pool?: boolean; } /** @@ -945,6 +954,7 @@ export interface RenderSubpassBuilder extends Setter { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; + _pool?: boolean; } /** @@ -973,6 +983,7 @@ export interface MultisampleRenderSubpassBuilder extends RenderSubpassBuilder { target: string, depthMode?: ResolveMode, stencilMode?: ResolveMode): void; + _pool?: boolean; } /** @@ -995,6 +1006,7 @@ export interface ComputeQueueBuilder extends Setter { threadGroupCountZ: number, material?: Material, passID?: number): void; + _pool?: boolean; } /** @@ -1078,6 +1090,7 @@ export interface ComputeSubpassBuilder extends Setter { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; + _pool?: boolean; } /** @@ -1148,6 +1161,7 @@ export interface RenderPassBuilder extends BasicRenderPassBuilder { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; + _pool?: boolean; } export interface MultisampleRenderPassBuilder extends BasicMultisampleRenderPassBuilder { @@ -1159,6 +1173,7 @@ export interface MultisampleRenderPassBuilder extends BasicMultisampleRenderPass name: string, accessType: AccessType, slotName: string): void; + _pool?: boolean; } /** @@ -1238,6 +1253,7 @@ export interface ComputePassBuilder extends Setter { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; + _pool?: boolean; } /** @@ -1408,6 +1424,7 @@ export interface Pipeline extends BasicPipeline { name: string, info: TextureInfo, type: string): number; + _pool?: boolean; } /** @@ -1427,6 +1444,7 @@ export interface PipelineBuilder { */ setup (cameras: Camera[], pipeline: BasicPipeline): void; onGlobalPipelineStateChanged? (): void; + _pool?: boolean; } /** @@ -1436,4 +1454,5 @@ export interface RenderingModule { getPassID (name: string): number; getSubpassID (passID: number, name: string): number; getPhaseID (subpassOrPassID: number, name: string): number; + _pool?: boolean; } diff --git a/cocos/rendering/custom/private.ts b/cocos/rendering/custom/private.ts index b4cae1f5d17..13566b9c74b 100644 --- a/cocos/rendering/custom/private.ts +++ b/cocos/rendering/custom/private.ts @@ -36,6 +36,7 @@ import { IProgramInfo } from '../../render-scene/core/program-lib'; export interface ProgramProxy { readonly name: string; readonly shader: Shader; + _pool?: boolean; } export interface ProgramLibrary { @@ -70,4 +71,5 @@ export interface ProgramLibrary { getProgramID (phaseID: number, programName: string): number; getDescriptorNameID (name: string): number; getDescriptorName (nameID: number): string; + _pool?: boolean; } diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index abf231b2ab9..8cfd6d5e5a3 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -55,6 +55,7 @@ export class ClearValue { y: number; z: number; w: number; + _pool?: boolean; } export class RasterView { @@ -107,6 +108,7 @@ export class RasterView { readonly clearColor: Color; slotID = 0; shaderStageFlags: ShaderStageFlagBit; + _pool?: boolean; } export class ComputeView { @@ -147,6 +149,7 @@ export class ComputeView { clearValueType: ClearValueType; readonly clearValue: ClearValue; shaderStageFlags: ShaderStageFlagBit; + _pool?: boolean; } export class ResourceDesc { @@ -174,6 +177,7 @@ export class ResourceDesc { textureFlags: TextureFlagBit = TextureFlagBit.NONE; flags: ResourceFlags = ResourceFlags.NONE; viewType: TextureType = TextureType.TEX2D; + _pool?: boolean; } export class ResourceTraits { @@ -184,6 +188,7 @@ export class ResourceTraits { this.residency = residency; } residency: ResourceResidency; + _pool?: boolean; } export class RenderSwapchain { @@ -202,6 +207,7 @@ export class RenderSwapchain { currentID = 0; numBackBuffers = 0; generation = 0xFFFFFFFF; + _pool?: boolean; } export class ResourceStates { @@ -209,6 +215,7 @@ export class ResourceStates { this.states = AccessFlagBit.NONE; } states: AccessFlagBit = AccessFlagBit.NONE; + _pool?: boolean; } export class ManagedBuffer { @@ -221,6 +228,7 @@ export class ManagedBuffer { } /*refcount*/ buffer: Buffer | null; fenceValue = 0; + _pool?: boolean; } export class PersistentBuffer { @@ -233,6 +241,7 @@ export class PersistentBuffer { } /*refcount*/ buffer: Buffer | null; fenceValue = 0; + _pool?: boolean; } export class ManagedTexture { @@ -245,6 +254,7 @@ export class ManagedTexture { } /*refcount*/ texture: Texture | null; fenceValue = 0; + _pool?: boolean; } export class PersistentTexture { @@ -257,6 +267,7 @@ export class PersistentTexture { } /*refcount*/ texture: Texture | null; fenceValue = 0; + _pool?: boolean; } export class ManagedResource { @@ -264,6 +275,7 @@ export class ManagedResource { this.unused = 0; } unused = 0; + _pool?: boolean; } export class Subpass { @@ -275,6 +287,7 @@ export class Subpass { readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); readonly resolvePairs: ResolvePair[] = []; + _pool?: boolean; } //================================================================= @@ -576,6 +589,7 @@ export class SubpassGraph implements BidirectionalGraph readonly _vertices: SubpassGraphVertex[] = []; readonly _names: string[] = []; readonly _subpasses: Subpass[] = []; + _pool?: boolean; } export class RasterSubpass { @@ -602,6 +616,7 @@ export class RasterSubpass { count: number; quality: number; showStatistics = false; + _pool?: boolean; } export class ComputeSubpass { @@ -616,6 +631,7 @@ export class ComputeSubpass { readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); subpassID: number; + _pool?: boolean; } export class RasterPass { @@ -649,6 +665,7 @@ export class RasterPass { version = 0; hashValue = 0; showStatistics = false; + _pool?: boolean; } export class PersistentRenderPassAndFramebuffer { @@ -668,6 +685,7 @@ export class PersistentRenderPassAndFramebuffer { readonly clearColors: Color[] = []; clearDepth = 0; clearStencil = 0; + _pool?: boolean; } export class FormatView { @@ -675,6 +693,7 @@ export class FormatView { this.format = Format.UNKNOWN; } format: Format = Format.UNKNOWN; + _pool?: boolean; } export class SubresourceView { @@ -696,6 +715,7 @@ export class SubresourceView { numArraySlices = 0; firstPlane = 0; numPlanes = 0; + _pool?: boolean; } //================================================================= @@ -1447,6 +1467,7 @@ export class ResourceGraph implements BidirectionalGraph readonly renderPasses: Map = new Map(); nextFenceValue = 0; version = 0; + _pool?: boolean; } export class ComputePass { @@ -1456,6 +1477,7 @@ export class ComputePass { } readonly computeViews: Map = new Map(); readonly textures: Map = new Map(); + _pool?: boolean; } export class ResolvePass { @@ -1463,6 +1485,7 @@ export class ResolvePass { this.resolvePairs.length = 0; } readonly resolvePairs: ResolvePair[] = []; + _pool?: boolean; } export class CopyPass { @@ -1472,6 +1495,7 @@ export class CopyPass { } readonly copyPairs: CopyPair[] = []; readonly uploadPairs: UploadPair[] = []; + _pool?: boolean; } export class MovePass { @@ -1479,6 +1503,7 @@ export class MovePass { this.movePairs.length = 0; } readonly movePairs: MovePair[] = []; + _pool?: boolean; } export class RaytracePass { @@ -1486,6 +1511,7 @@ export class RaytracePass { this.computeViews.clear(); } readonly computeViews: Map = new Map(); + _pool?: boolean; } export class ClearView { @@ -1502,6 +1528,7 @@ export class ClearView { slotName: string; clearFlags: ClearFlagBit; readonly clearColor: Color; + _pool?: boolean; } export class RenderQueue { @@ -1517,6 +1544,7 @@ export class RenderQueue { hint: QueueHint; phaseID: number; viewport: Viewport | null = null; + _pool?: boolean; } export enum CullingFlags { @@ -1562,6 +1590,7 @@ export class SceneData { flags: SceneFlags; cullingFlags: CullingFlags; /*refcount*/ shadingLight: Light | null; + _pool?: boolean; } export class Dispatch { @@ -1596,6 +1625,7 @@ export class Dispatch { threadGroupCountX: number; threadGroupCountY: number; threadGroupCountZ: number; + _pool?: boolean; } export class Blit { @@ -1615,6 +1645,7 @@ export class Blit { passID: number; sceneFlags: SceneFlags; /*pointer*/ camera: Camera | null; + _pool?: boolean; } export class RenderData { @@ -1630,6 +1661,7 @@ export class RenderData { readonly textures: Map = new Map(); readonly samplers: Map = new Map(); custom = ''; + _pool?: boolean; } //================================================================= @@ -2514,6 +2546,7 @@ export class RenderGraph implements BidirectionalGraph readonly _valid: boolean[] = []; readonly index: Map = new Map(); readonly sortedVertices: number[] = []; + _pool?: boolean; } export class RenderGraphObjectPoolSettings { @@ -2670,6 +2703,7 @@ export class RenderGraphObjectPool { v = new ClearValue(); } else { v = this._clearValue.add(); + v._pool = true; } v.reset(x, y, z, w); return v; @@ -2688,6 +2722,7 @@ export class RenderGraphObjectPool { v = new RasterView(); } else { v = this._rasterView.add(); + v._pool = true; } v.reset(slotName, accessType, attachmentType, loadOp, storeOp, clearFlags, shaderStageFlags); return v; @@ -2704,6 +2739,7 @@ export class RenderGraphObjectPool { v = new ComputeView(); } else { v = this._computeView.add(); + v._pool = true; } v.reset(name, accessType, clearFlags, clearValueType, shaderStageFlags); return v; @@ -2714,6 +2750,7 @@ export class RenderGraphObjectPool { v = new ResourceDesc(); } else { v = this._resourceDesc.add(); + v._pool = true; } v.reset(); return v; @@ -2726,6 +2763,7 @@ export class RenderGraphObjectPool { v = new ResourceTraits(); } else { v = this._resourceTraits.add(); + v._pool = true; } v.reset(residency); return v; @@ -2738,6 +2776,7 @@ export class RenderGraphObjectPool { v = new RenderSwapchain(); } else { v = this._renderSwapchain.add(); + v._pool = true; } v.reset(swapchain); return v; @@ -2748,6 +2787,7 @@ export class RenderGraphObjectPool { v = new ResourceStates(); } else { v = this._resourceStates.add(); + v._pool = true; } v.reset(); return v; @@ -2760,6 +2800,7 @@ export class RenderGraphObjectPool { v = new ManagedBuffer(); } else { v = this._managedBuffer.add(); + v._pool = true; } v.reset(buffer); return v; @@ -2772,6 +2813,7 @@ export class RenderGraphObjectPool { v = new PersistentBuffer(); } else { v = this._persistentBuffer.add(); + v._pool = true; } v.reset(buffer); return v; @@ -2784,6 +2826,7 @@ export class RenderGraphObjectPool { v = new ManagedTexture(); } else { v = this._managedTexture.add(); + v._pool = true; } v.reset(texture); return v; @@ -2796,6 +2839,7 @@ export class RenderGraphObjectPool { v = new PersistentTexture(); } else { v = this._persistentTexture.add(); + v._pool = true; } v.reset(texture); return v; @@ -2806,6 +2850,7 @@ export class RenderGraphObjectPool { v = new ManagedResource(); } else { v = this._managedResource.add(); + v._pool = true; } v.reset(); return v; @@ -2816,6 +2861,7 @@ export class RenderGraphObjectPool { v = new Subpass(); } else { v = this._subpass.add(); + v._pool = true; } v.reset(); return v; @@ -2826,6 +2872,7 @@ export class RenderGraphObjectPool { v = new SubpassGraph(); } else { v = this._subpassGraph.add(); + v._pool = true; } v.clear(); return v; @@ -2840,6 +2887,7 @@ export class RenderGraphObjectPool { v = new RasterSubpass(); } else { v = this._rasterSubpass.add(); + v._pool = true; } v.reset(subpassID, count, quality); return v; @@ -2852,6 +2900,7 @@ export class RenderGraphObjectPool { v = new ComputeSubpass(); } else { v = this._computeSubpass.add(); + v._pool = true; } v.reset(subpassID); return v; @@ -2862,6 +2911,7 @@ export class RenderGraphObjectPool { v = new RasterPass(); } else { v = this._rasterPass.add(); + v._pool = true; } v.reset(); return v; @@ -2875,6 +2925,7 @@ export class RenderGraphObjectPool { v = new PersistentRenderPassAndFramebuffer(); } else { v = this._persistentRenderPassAndFramebuffer.add(); + v._pool = true; } v.reset(renderPass, framebuffer); return v; @@ -2885,6 +2936,7 @@ export class RenderGraphObjectPool { v = new FormatView(); } else { v = this._formatView.add(); + v._pool = true; } v.reset(); return v; @@ -2895,6 +2947,7 @@ export class RenderGraphObjectPool { v = new SubresourceView(); } else { v = this._subresourceView.add(); + v._pool = true; } v.reset(); return v; @@ -2905,6 +2958,7 @@ export class RenderGraphObjectPool { v = new ResourceGraph(); } else { v = this._resourceGraph.add(); + v._pool = true; } v.clear(); return v; @@ -2915,6 +2969,7 @@ export class RenderGraphObjectPool { v = new ComputePass(); } else { v = this._computePass.add(); + v._pool = true; } v.reset(); return v; @@ -2925,6 +2980,7 @@ export class RenderGraphObjectPool { v = new ResolvePass(); } else { v = this._resolvePass.add(); + v._pool = true; } v.reset(); return v; @@ -2935,6 +2991,7 @@ export class RenderGraphObjectPool { v = new CopyPass(); } else { v = this._copyPass.add(); + v._pool = true; } v.reset(); return v; @@ -2945,6 +3002,7 @@ export class RenderGraphObjectPool { v = new MovePass(); } else { v = this._movePass.add(); + v._pool = true; } v.reset(); return v; @@ -2955,6 +3013,7 @@ export class RenderGraphObjectPool { v = new RaytracePass(); } else { v = this._raytracePass.add(); + v._pool = true; } v.reset(); return v; @@ -2968,6 +3027,7 @@ export class RenderGraphObjectPool { v = new ClearView(); } else { v = this._clearView.add(); + v._pool = true; } v.reset(slotName, clearFlags); return v; @@ -2981,6 +3041,7 @@ export class RenderGraphObjectPool { v = new RenderQueue(); } else { v = this._renderQueue.add(); + v._pool = true; } v.reset(hint, phaseID); return v; @@ -2997,6 +3058,7 @@ export class RenderGraphObjectPool { v = new SceneData(); } else { v = this._sceneData.add(); + v._pool = true; } v.reset(scene, camera, flags, cullingFlags, shadingLight); return v; @@ -3013,6 +3075,7 @@ export class RenderGraphObjectPool { v = new Dispatch(); } else { v = this._dispatch.add(); + v._pool = true; } v.reset(material, passID, threadGroupCountX, threadGroupCountY, threadGroupCountZ); return v; @@ -3028,6 +3091,7 @@ export class RenderGraphObjectPool { v = new Blit(); } else { v = this._blit.add(); + v._pool = true; } v.reset(material, passID, sceneFlags, camera); return v; @@ -3038,6 +3102,7 @@ export class RenderGraphObjectPool { v = new RenderData(); } else { v = this._renderData.add(); + v._pool = true; } v.reset(); return v; @@ -3048,6 +3113,7 @@ export class RenderGraphObjectPool { v = new RenderGraph(); } else { v = this._renderGraph.add(); + v._pool = true; } v.clear(); return v; diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index f098a245129..21d307d1d42 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -307,6 +307,7 @@ export class LightInfo { /*pointer*/ probe: ReflectionProbe | null; level: number; culledByLight: boolean; + _pool?: boolean; } export enum DescriptorTypeOrder { @@ -356,6 +357,7 @@ export class Descriptor { } type: Type; count = 1; + _pool?: boolean; } export class DescriptorBlock { @@ -369,6 +371,7 @@ export class DescriptorBlock { readonly uniformBlocks: Map = new Map(); capacity = 0; count = 0; + _pool?: boolean; } export class DescriptorBlockFlattened { @@ -386,6 +389,7 @@ export class DescriptorBlockFlattened { readonly uniformBlocks: UniformBlock[] = []; capacity = 0; count = 0; + _pool?: boolean; } export class DescriptorBlockIndex { @@ -399,6 +403,7 @@ export class DescriptorBlockIndex { parameterType: ParameterType; descriptorType: DescriptorTypeOrder; visibility: ShaderStageFlagBit; + _pool?: boolean; } export enum ResolveFlags { @@ -440,6 +445,7 @@ export class ResolvePair { resolveFlags: ResolveFlags; mode: ResolveMode; mode1: ResolveMode; + _pool?: boolean; } export class CopyPair { @@ -499,6 +505,7 @@ export class CopyPair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; + _pool?: boolean; } export class UploadPair { @@ -542,6 +549,7 @@ export class UploadPair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; + _pool?: boolean; } export class MovePair { @@ -586,6 +594,7 @@ export class MovePair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; + _pool?: boolean; } export class PipelineStatistics { @@ -613,6 +622,7 @@ export class PipelineStatistics { numFreeDescriptorSets = 0; numInstancingBuffers = 0; numInstancingUniformBlocks = 0; + _pool?: boolean; } export class RenderCommonObjectPoolSettings { @@ -676,6 +686,7 @@ export class RenderCommonObjectPool { v = new LightInfo(); } else { v = this._lightInfo.add(); + v._pool = true; } v.reset(light, level, culledByLight, probe); return v; @@ -688,6 +699,7 @@ export class RenderCommonObjectPool { v = new Descriptor(); } else { v = this._descriptor.add(); + v._pool = true; } v.reset(type); return v; @@ -698,6 +710,7 @@ export class RenderCommonObjectPool { v = new DescriptorBlock(); } else { v = this._descriptorBlock.add(); + v._pool = true; } v.reset(); return v; @@ -708,6 +721,7 @@ export class RenderCommonObjectPool { v = new DescriptorBlockFlattened(); } else { v = this._descriptorBlockFlattened.add(); + v._pool = true; } v.reset(); return v; @@ -723,6 +737,7 @@ export class RenderCommonObjectPool { v = new DescriptorBlockIndex(); } else { v = this._descriptorBlockIndex.add(); + v._pool = true; } v.updateFrequency = updateFrequency; v.parameterType = parameterType; @@ -742,6 +757,7 @@ export class RenderCommonObjectPool { v = new ResolvePair(); } else { v = this._resolvePair.add(); + v._pool = true; } v.reset(source, target, resolveFlags, mode, mode1); return v; @@ -763,6 +779,7 @@ export class RenderCommonObjectPool { v = new CopyPair(); } else { v = this._copyPair.add(); + v._pool = true; } v.reset(source, target, mipLevels, numSlices, sourceMostDetailedMip, sourceFirstSlice, sourcePlaneSlice, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; @@ -780,6 +797,7 @@ export class RenderCommonObjectPool { v = new UploadPair(); } else { v = this._uploadPair.add(); + v._pool = true; } v.reset(target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; @@ -798,6 +816,7 @@ export class RenderCommonObjectPool { v = new MovePair(); } else { v = this._movePair.add(); + v._pool = true; } v.reset(source, target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; @@ -808,6 +827,7 @@ export class RenderCommonObjectPool { v = new PipelineStatistics(); } else { v = this._pipelineStatistics.add(); + v._pool = true; } v.reset(); return v; diff --git a/cocos/rendering/custom/web-types.ts b/cocos/rendering/custom/web-types.ts index b275b9abde9..1760987eb42 100644 --- a/cocos/rendering/custom/web-types.ts +++ b/cocos/rendering/custom/web-types.ts @@ -51,9 +51,11 @@ export class ProgramInfo { readonly attributes: Attribute[]; readonly blockSizes: number[]; readonly handleMap: Record; + _pool?: boolean; } export class ProgramGroup { readonly programInfos: Map = new Map(); readonly programProxies: Map = new Map(); + _pool?: boolean; } From 1f9ef76e0f5dcc01d710efcba6c33b38034a6fbe Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Wed, 20 Sep 2023 17:55:51 +0800 Subject: [PATCH 68/82] add create debug --- cocos/rendering/custom/layout-graph.ts | 67 +++++++------- cocos/rendering/custom/render-graph.ts | 115 ++++++++++++++----------- cocos/rendering/custom/types.ts | 33 ++++--- 3 files changed, 122 insertions(+), 93 deletions(-) diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index b50bc99c0a1..9a4d2e3e587 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -1437,9 +1437,9 @@ export class LayoutGraphObjectPool { this._renderPhaseData.reset(); this._layoutGraphData.reset(); } - createDescriptorDB (): DescriptorDB { + createDescriptorDB (isDebug = true): DescriptorDB { let v: DescriptorDB; - if (this.debug) { + if (isDebug) { v = new DescriptorDB(); } else { v = this._descriptorDB.add(); @@ -1448,9 +1448,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createRenderPhase (): RenderPhase { + createRenderPhase (isDebug = true): RenderPhase { let v: RenderPhase; - if (this.debug) { + if (isDebug) { v = new RenderPhase(); } else { v = this._renderPhase.add(); @@ -1459,9 +1459,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createLayoutGraph (): LayoutGraph { + createLayoutGraph (isDebug = true): LayoutGraph { let v: LayoutGraph; - if (this.debug) { + if (isDebug) { v = new LayoutGraph(); } else { v = this._layoutGraph.add(); @@ -1474,9 +1474,10 @@ export class LayoutGraphObjectPool { uniformID = 0xFFFFFFFF, uniformType: Type = Type.UNKNOWN, offset = 0, + isDebug = true, ): UniformData { let v: UniformData; - if (this.debug) { + if (isDebug) { v = new UniformData(); } else { v = this._uniformData.add(); @@ -1485,9 +1486,9 @@ export class LayoutGraphObjectPool { v.reset(uniformID, uniformType, offset); return v; } - createUniformBlockData (): UniformBlockData { + createUniformBlockData (isDebug = true): UniformBlockData { let v: UniformBlockData; - if (this.debug) { + if (isDebug) { v = new UniformBlockData(); } else { v = this._uniformBlockData.add(); @@ -1500,9 +1501,10 @@ export class LayoutGraphObjectPool { descriptorID = 0, type: Type = Type.UNKNOWN, count = 1, + isDebug = true, ): DescriptorData { let v: DescriptorData; - if (this.debug) { + if (isDebug) { v = new DescriptorData(); } else { v = this._descriptorData.add(); @@ -1515,9 +1517,10 @@ export class LayoutGraphObjectPool { type: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, capacity = 0, + isDebug = true, ): DescriptorBlockData { let v: DescriptorBlockData; - if (this.debug) { + if (isDebug) { v = new DescriptorBlockData(); } else { v = this._descriptorBlockData.add(); @@ -1529,9 +1532,10 @@ export class LayoutGraphObjectPool { createDescriptorSetLayoutData ( slot = 0xFFFFFFFF, capacity = 0, + isDebug = true, ): DescriptorSetLayoutData { let v: DescriptorSetLayoutData; - if (this.debug) { + if (isDebug) { v = new DescriptorSetLayoutData(); } else { v = this._descriptorSetLayoutData.add(); @@ -1543,9 +1547,10 @@ export class LayoutGraphObjectPool { createDescriptorSetData ( descriptorSetLayout: DescriptorSetLayout | null = null, descriptorSet: DescriptorSet | null = null, + isDebug = true, ): DescriptorSetData { let v: DescriptorSetData; - if (this.debug) { + if (isDebug) { v = new DescriptorSetData(); } else { v = this._descriptorSetData.add(); @@ -1554,9 +1559,9 @@ export class LayoutGraphObjectPool { v.reset(descriptorSetLayout, descriptorSet); return v; } - createPipelineLayoutData (): PipelineLayoutData { + createPipelineLayoutData (isDebug = true): PipelineLayoutData { let v: PipelineLayoutData; - if (this.debug) { + if (isDebug) { v = new PipelineLayoutData(); } else { v = this._pipelineLayoutData.add(); @@ -1565,9 +1570,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createShaderBindingData (): ShaderBindingData { + createShaderBindingData (isDebug = true): ShaderBindingData { let v: ShaderBindingData; - if (this.debug) { + if (isDebug) { v = new ShaderBindingData(); } else { v = this._shaderBindingData.add(); @@ -1576,9 +1581,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createShaderLayoutData (): ShaderLayoutData { + createShaderLayoutData (isDebug = true): ShaderLayoutData { let v: ShaderLayoutData; - if (this.debug) { + if (isDebug) { v = new ShaderLayoutData(); } else { v = this._shaderLayoutData.add(); @@ -1587,9 +1592,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createTechniqueData (): TechniqueData { + createTechniqueData (isDebug = true): TechniqueData { let v: TechniqueData; - if (this.debug) { + if (isDebug) { v = new TechniqueData(); } else { v = this._techniqueData.add(); @@ -1598,9 +1603,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createEffectData (): EffectData { + createEffectData (isDebug = true): EffectData { let v: EffectData; - if (this.debug) { + if (isDebug) { v = new EffectData(); } else { v = this._effectData.add(); @@ -1609,9 +1614,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createShaderProgramData (): ShaderProgramData { + createShaderProgramData (isDebug = true): ShaderProgramData { let v: ShaderProgramData; - if (this.debug) { + if (isDebug) { v = new ShaderProgramData(); } else { v = this._shaderProgramData.add(); @@ -1620,9 +1625,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createRenderStageData (): RenderStageData { + createRenderStageData (isDebug = true): RenderStageData { let v: RenderStageData; - if (this.debug) { + if (isDebug) { v = new RenderStageData(); } else { v = this._renderStageData.add(); @@ -1631,9 +1636,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createRenderPhaseData (): RenderPhaseData { + createRenderPhaseData (isDebug = true): RenderPhaseData { let v: RenderPhaseData; - if (this.debug) { + if (isDebug) { v = new RenderPhaseData(); } else { v = this._renderPhaseData.add(); @@ -1642,9 +1647,9 @@ export class LayoutGraphObjectPool { v.reset(); return v; } - createLayoutGraphData (): LayoutGraphData { + createLayoutGraphData (isDebug = true): LayoutGraphData { let v: LayoutGraphData; - if (this.debug) { + if (isDebug) { v = new LayoutGraphData(); } else { v = this._layoutGraphData.add(); diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 8cfd6d5e5a3..05b4e000448 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -2697,9 +2697,10 @@ export class RenderGraphObjectPool { y = 0, z = 0, w = 0, + isDebug = true, ): ClearValue { let v: ClearValue; - if (this.debug) { + if (isDebug) { v = new ClearValue(); } else { v = this._clearValue.add(); @@ -2716,9 +2717,10 @@ export class RenderGraphObjectPool { storeOp: StoreOp = StoreOp.STORE, clearFlags: ClearFlagBit = ClearFlagBit.ALL, shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + isDebug = true, ): RasterView { let v: RasterView; - if (this.debug) { + if (isDebug) { v = new RasterView(); } else { v = this._rasterView.add(); @@ -2733,9 +2735,10 @@ export class RenderGraphObjectPool { clearFlags: ClearFlagBit = ClearFlagBit.NONE, clearValueType: ClearValueType = ClearValueType.NONE, shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + isDebug = true, ): ComputeView { let v: ComputeView; - if (this.debug) { + if (isDebug) { v = new ComputeView(); } else { v = this._computeView.add(); @@ -2744,9 +2747,9 @@ export class RenderGraphObjectPool { v.reset(name, accessType, clearFlags, clearValueType, shaderStageFlags); return v; } - createResourceDesc (): ResourceDesc { + createResourceDesc (isDebug = true): ResourceDesc { let v: ResourceDesc; - if (this.debug) { + if (isDebug) { v = new ResourceDesc(); } else { v = this._resourceDesc.add(); @@ -2757,9 +2760,10 @@ export class RenderGraphObjectPool { } createResourceTraits ( residency: ResourceResidency = ResourceResidency.MANAGED, + isDebug = true, ): ResourceTraits { let v: ResourceTraits; - if (this.debug) { + if (isDebug) { v = new ResourceTraits(); } else { v = this._resourceTraits.add(); @@ -2770,9 +2774,10 @@ export class RenderGraphObjectPool { } createRenderSwapchain ( swapchain: Swapchain | null = null, + isDebug = true, ): RenderSwapchain { let v: RenderSwapchain; - if (this.debug) { + if (isDebug) { v = new RenderSwapchain(); } else { v = this._renderSwapchain.add(); @@ -2781,9 +2786,9 @@ export class RenderGraphObjectPool { v.reset(swapchain); return v; } - createResourceStates (): ResourceStates { + createResourceStates (isDebug = true): ResourceStates { let v: ResourceStates; - if (this.debug) { + if (isDebug) { v = new ResourceStates(); } else { v = this._resourceStates.add(); @@ -2794,9 +2799,10 @@ export class RenderGraphObjectPool { } createManagedBuffer ( buffer: Buffer | null = null, + isDebug = true, ): ManagedBuffer { let v: ManagedBuffer; - if (this.debug) { + if (isDebug) { v = new ManagedBuffer(); } else { v = this._managedBuffer.add(); @@ -2807,9 +2813,10 @@ export class RenderGraphObjectPool { } createPersistentBuffer ( buffer: Buffer | null = null, + isDebug = true, ): PersistentBuffer { let v: PersistentBuffer; - if (this.debug) { + if (isDebug) { v = new PersistentBuffer(); } else { v = this._persistentBuffer.add(); @@ -2820,9 +2827,10 @@ export class RenderGraphObjectPool { } createManagedTexture ( texture: Texture | null = null, + isDebug = true, ): ManagedTexture { let v: ManagedTexture; - if (this.debug) { + if (isDebug) { v = new ManagedTexture(); } else { v = this._managedTexture.add(); @@ -2833,9 +2841,10 @@ export class RenderGraphObjectPool { } createPersistentTexture ( texture: Texture | null = null, + isDebug = true, ): PersistentTexture { let v: PersistentTexture; - if (this.debug) { + if (isDebug) { v = new PersistentTexture(); } else { v = this._persistentTexture.add(); @@ -2844,9 +2853,9 @@ export class RenderGraphObjectPool { v.reset(texture); return v; } - createManagedResource (): ManagedResource { + createManagedResource (isDebug = true): ManagedResource { let v: ManagedResource; - if (this.debug) { + if (isDebug) { v = new ManagedResource(); } else { v = this._managedResource.add(); @@ -2855,9 +2864,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createSubpass (): Subpass { + createSubpass (isDebug = true): Subpass { let v: Subpass; - if (this.debug) { + if (isDebug) { v = new Subpass(); } else { v = this._subpass.add(); @@ -2866,9 +2875,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createSubpassGraph (): SubpassGraph { + createSubpassGraph (isDebug = true): SubpassGraph { let v: SubpassGraph; - if (this.debug) { + if (isDebug) { v = new SubpassGraph(); } else { v = this._subpassGraph.add(); @@ -2881,9 +2890,10 @@ export class RenderGraphObjectPool { subpassID = 0xFFFFFFFF, count = 1, quality = 0, + isDebug = true, ): RasterSubpass { let v: RasterSubpass; - if (this.debug) { + if (isDebug) { v = new RasterSubpass(); } else { v = this._rasterSubpass.add(); @@ -2894,9 +2904,10 @@ export class RenderGraphObjectPool { } createComputeSubpass ( subpassID = 0xFFFFFFFF, + isDebug = true, ): ComputeSubpass { let v: ComputeSubpass; - if (this.debug) { + if (isDebug) { v = new ComputeSubpass(); } else { v = this._computeSubpass.add(); @@ -2905,9 +2916,9 @@ export class RenderGraphObjectPool { v.reset(subpassID); return v; } - createRasterPass (): RasterPass { + createRasterPass (isDebug = true): RasterPass { let v: RasterPass; - if (this.debug) { + if (isDebug) { v = new RasterPass(); } else { v = this._rasterPass.add(); @@ -2919,9 +2930,10 @@ export class RenderGraphObjectPool { createPersistentRenderPassAndFramebuffer ( renderPass: RenderPass | null = null, framebuffer: Framebuffer | null = null, + isDebug = true, ): PersistentRenderPassAndFramebuffer { let v: PersistentRenderPassAndFramebuffer; - if (this.debug) { + if (isDebug) { v = new PersistentRenderPassAndFramebuffer(); } else { v = this._persistentRenderPassAndFramebuffer.add(); @@ -2930,9 +2942,9 @@ export class RenderGraphObjectPool { v.reset(renderPass, framebuffer); return v; } - createFormatView (): FormatView { + createFormatView (isDebug = true): FormatView { let v: FormatView; - if (this.debug) { + if (isDebug) { v = new FormatView(); } else { v = this._formatView.add(); @@ -2941,9 +2953,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createSubresourceView (): SubresourceView { + createSubresourceView (isDebug = true): SubresourceView { let v: SubresourceView; - if (this.debug) { + if (isDebug) { v = new SubresourceView(); } else { v = this._subresourceView.add(); @@ -2952,9 +2964,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createResourceGraph (): ResourceGraph { + createResourceGraph (isDebug = true): ResourceGraph { let v: ResourceGraph; - if (this.debug) { + if (isDebug) { v = new ResourceGraph(); } else { v = this._resourceGraph.add(); @@ -2963,9 +2975,9 @@ export class RenderGraphObjectPool { v.clear(); return v; } - createComputePass (): ComputePass { + createComputePass (isDebug = true): ComputePass { let v: ComputePass; - if (this.debug) { + if (isDebug) { v = new ComputePass(); } else { v = this._computePass.add(); @@ -2974,9 +2986,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createResolvePass (): ResolvePass { + createResolvePass (isDebug = true): ResolvePass { let v: ResolvePass; - if (this.debug) { + if (isDebug) { v = new ResolvePass(); } else { v = this._resolvePass.add(); @@ -2985,9 +2997,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createCopyPass (): CopyPass { + createCopyPass (isDebug = true): CopyPass { let v: CopyPass; - if (this.debug) { + if (isDebug) { v = new CopyPass(); } else { v = this._copyPass.add(); @@ -2996,9 +3008,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createMovePass (): MovePass { + createMovePass (isDebug = true): MovePass { let v: MovePass; - if (this.debug) { + if (isDebug) { v = new MovePass(); } else { v = this._movePass.add(); @@ -3007,9 +3019,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createRaytracePass (): RaytracePass { + createRaytracePass (isDebug = true): RaytracePass { let v: RaytracePass; - if (this.debug) { + if (isDebug) { v = new RaytracePass(); } else { v = this._raytracePass.add(); @@ -3021,9 +3033,10 @@ export class RenderGraphObjectPool { createClearView ( slotName = '', clearFlags: ClearFlagBit = ClearFlagBit.ALL, + isDebug = true, ): ClearView { let v: ClearView; - if (this.debug) { + if (isDebug) { v = new ClearView(); } else { v = this._clearView.add(); @@ -3035,9 +3048,10 @@ export class RenderGraphObjectPool { createRenderQueue ( hint: QueueHint = QueueHint.RENDER_OPAQUE, phaseID = 0xFFFFFFFF, + isDebug = true, ): RenderQueue { let v: RenderQueue; - if (this.debug) { + if (isDebug) { v = new RenderQueue(); } else { v = this._renderQueue.add(); @@ -3052,9 +3066,10 @@ export class RenderGraphObjectPool { flags: SceneFlags = SceneFlags.NONE, cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, shadingLight: Light | null = null, + isDebug = true, ): SceneData { let v: SceneData; - if (this.debug) { + if (isDebug) { v = new SceneData(); } else { v = this._sceneData.add(); @@ -3069,9 +3084,10 @@ export class RenderGraphObjectPool { threadGroupCountX = 0, threadGroupCountY = 0, threadGroupCountZ = 0, + isDebug = true, ): Dispatch { let v: Dispatch; - if (this.debug) { + if (isDebug) { v = new Dispatch(); } else { v = this._dispatch.add(); @@ -3085,9 +3101,10 @@ export class RenderGraphObjectPool { passID = 0, sceneFlags: SceneFlags = SceneFlags.NONE, camera: Camera | null = null, + isDebug = true, ): Blit { let v: Blit; - if (this.debug) { + if (isDebug) { v = new Blit(); } else { v = this._blit.add(); @@ -3096,9 +3113,9 @@ export class RenderGraphObjectPool { v.reset(material, passID, sceneFlags, camera); return v; } - createRenderData (): RenderData { + createRenderData (isDebug = true): RenderData { let v: RenderData; - if (this.debug) { + if (isDebug) { v = new RenderData(); } else { v = this._renderData.add(); @@ -3107,9 +3124,9 @@ export class RenderGraphObjectPool { v.reset(); return v; } - createRenderGraph (): RenderGraph { + createRenderGraph (isDebug = true): RenderGraph { let v: RenderGraph; - if (this.debug) { + if (isDebug) { v = new RenderGraph(); } else { v = this._renderGraph.add(); diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 21d307d1d42..21ac51db9ba 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -680,9 +680,10 @@ export class RenderCommonObjectPool { level = 0, culledByLight = false, probe: ReflectionProbe | null = null, + isDebug = true, ): LightInfo { let v: LightInfo; - if (this.debug) { + if (isDebug) { v = new LightInfo(); } else { v = this._lightInfo.add(); @@ -693,9 +694,10 @@ export class RenderCommonObjectPool { } createDescriptor ( type: Type = Type.UNKNOWN, + isDebug = true, ): Descriptor { let v: Descriptor; - if (this.debug) { + if (isDebug) { v = new Descriptor(); } else { v = this._descriptor.add(); @@ -704,9 +706,9 @@ export class RenderCommonObjectPool { v.reset(type); return v; } - createDescriptorBlock (): DescriptorBlock { + createDescriptorBlock (isDebug = true): DescriptorBlock { let v: DescriptorBlock; - if (this.debug) { + if (isDebug) { v = new DescriptorBlock(); } else { v = this._descriptorBlock.add(); @@ -715,9 +717,9 @@ export class RenderCommonObjectPool { v.reset(); return v; } - createDescriptorBlockFlattened (): DescriptorBlockFlattened { + createDescriptorBlockFlattened (isDebug = true): DescriptorBlockFlattened { let v: DescriptorBlockFlattened; - if (this.debug) { + if (isDebug) { v = new DescriptorBlockFlattened(); } else { v = this._descriptorBlockFlattened.add(); @@ -731,9 +733,10 @@ export class RenderCommonObjectPool { parameterType: ParameterType = ParameterType.CONSTANTS, descriptorType: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, + isDebug = true, ): DescriptorBlockIndex { let v: DescriptorBlockIndex; - if (this.debug) { + if (isDebug) { v = new DescriptorBlockIndex(); } else { v = this._descriptorBlockIndex.add(); @@ -751,9 +754,10 @@ export class RenderCommonObjectPool { resolveFlags: ResolveFlags = ResolveFlags.NONE, mode: ResolveMode = ResolveMode.SAMPLE_ZERO, mode1: ResolveMode = ResolveMode.SAMPLE_ZERO, + isDebug = true, ): ResolvePair { let v: ResolvePair; - if (this.debug) { + if (isDebug) { v = new ResolvePair(); } else { v = this._resolvePair.add(); @@ -773,9 +777,10 @@ export class RenderCommonObjectPool { targetMostDetailedMip = 0, targetFirstSlice = 0, targetPlaneSlice = 0, + isDebug = true, ): CopyPair { let v: CopyPair; - if (this.debug) { + if (isDebug) { v = new CopyPair(); } else { v = this._copyPair.add(); @@ -791,9 +796,10 @@ export class RenderCommonObjectPool { targetMostDetailedMip = 0, targetFirstSlice = 0, targetPlaneSlice = 0, + isDebug = true, ): UploadPair { let v: UploadPair; - if (this.debug) { + if (isDebug) { v = new UploadPair(); } else { v = this._uploadPair.add(); @@ -810,9 +816,10 @@ export class RenderCommonObjectPool { targetMostDetailedMip = 0, targetFirstSlice = 0, targetPlaneSlice = 0, + isDebug = true, ): MovePair { let v: MovePair; - if (this.debug) { + if (isDebug) { v = new MovePair(); } else { v = this._movePair.add(); @@ -821,9 +828,9 @@ export class RenderCommonObjectPool { v.reset(source, target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } - createPipelineStatistics (): PipelineStatistics { + createPipelineStatistics (isDebug = true): PipelineStatistics { let v: PipelineStatistics; - if (this.debug) { + if (isDebug) { v = new PipelineStatistics(); } else { v = this._pipelineStatistics.add(); From a3982225e359a40f7ecb33592ac406031012fe18 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 21 Sep 2023 11:30:54 +0800 Subject: [PATCH 69/82] remove debug --- cocos/rendering/custom/archive.ts | 2 - cocos/rendering/custom/layout-graph.ts | 194 +++----------- cocos/rendering/custom/pipeline.ts | 19 -- cocos/rendering/custom/private.ts | 2 - cocos/rendering/custom/render-graph.ts | 347 ++++--------------------- cocos/rendering/custom/types.ts | 104 +------- cocos/rendering/custom/web-types.ts | 2 - 7 files changed, 93 insertions(+), 577 deletions(-) diff --git a/cocos/rendering/custom/archive.ts b/cocos/rendering/custom/archive.ts index 3d1ea4859c7..9b513ffc2bd 100644 --- a/cocos/rendering/custom/archive.ts +++ b/cocos/rendering/custom/archive.ts @@ -32,12 +32,10 @@ export interface OutputArchive { writeBool (value: boolean): void; writeNumber (value: number): void; writeString (value: string): void; - _pool?: boolean; } export interface InputArchive { readBool (): boolean; readNumber (): number; readString (): string; - _pool?: boolean; } diff --git a/cocos/rendering/custom/layout-graph.ts b/cocos/rendering/custom/layout-graph.ts index 9a4d2e3e587..4e8d25991dd 100644 --- a/cocos/rendering/custom/layout-graph.ts +++ b/cocos/rendering/custom/layout-graph.ts @@ -40,7 +40,6 @@ export class DescriptorDB { this.blocks.clear(); } readonly blocks: Map = new Map(); - _pool?: boolean; } export class RenderPhase { @@ -48,7 +47,6 @@ export class RenderPhase { this.shaders.clear(); } readonly shaders: Set = new Set(); - _pool?: boolean; } export enum RenderPassType { @@ -588,7 +586,6 @@ export class LayoutGraph implements BidirectionalGraph readonly _vertices: LayoutGraphVertex[] = []; readonly _names: string[] = []; readonly _descriptors: DescriptorDB[] = []; - _pool?: boolean; } export class UniformData { @@ -607,7 +604,6 @@ export class UniformData { uniformType: Type; offset: number; size = 0; - _pool?: boolean; } export class UniformBlockData { @@ -617,7 +613,6 @@ export class UniformBlockData { } bufferSize = 0; readonly uniforms: UniformData[] = []; - _pool?: boolean; } export class DescriptorData { @@ -634,7 +629,6 @@ export class DescriptorData { descriptorID: number; type: Type; count: number; - _pool?: boolean; } export class DescriptorBlockData { @@ -655,7 +649,6 @@ export class DescriptorBlockData { offset = 0; capacity: number; readonly descriptors: DescriptorData[] = []; - _pool?: boolean; } export class DescriptorSetLayoutData { @@ -691,7 +684,6 @@ export class DescriptorSetLayoutData { readonly descriptorBlocks: DescriptorBlockData[]; readonly uniformBlocks: Map; readonly bindingMap: Map; - _pool?: boolean; } export class DescriptorSetData { @@ -710,7 +702,6 @@ export class DescriptorSetData { readonly descriptorSetLayoutInfo: DescriptorSetLayoutInfo = new DescriptorSetLayoutInfo(); /*refcount*/ descriptorSetLayout: DescriptorSetLayout | null; /*refcount*/ descriptorSet: DescriptorSet | null; - _pool?: boolean; } export class PipelineLayoutData { @@ -718,7 +709,6 @@ export class PipelineLayoutData { this.descriptorSets.clear(); } readonly descriptorSets: Map = new Map(); - _pool?: boolean; } export class ShaderBindingData { @@ -726,7 +716,6 @@ export class ShaderBindingData { this.descriptorBindings.clear(); } readonly descriptorBindings: Map = new Map(); - _pool?: boolean; } export class ShaderLayoutData { @@ -736,7 +725,6 @@ export class ShaderLayoutData { } readonly layoutData: Map = new Map(); readonly bindingData: Map = new Map(); - _pool?: boolean; } export class TechniqueData { @@ -744,7 +732,6 @@ export class TechniqueData { this.passes.length = 0; } readonly passes: ShaderLayoutData[] = []; - _pool?: boolean; } export class EffectData { @@ -752,7 +739,6 @@ export class EffectData { this.techniques.clear(); } readonly techniques: Map = new Map(); - _pool?: boolean; } export class ShaderProgramData { @@ -762,7 +748,6 @@ export class ShaderProgramData { } readonly layout: PipelineLayoutData = new PipelineLayoutData(); /*refcount*/ pipelineLayout: PipelineLayout | null = null; - _pool?: boolean; } export class RenderStageData { @@ -770,7 +755,6 @@ export class RenderStageData { this.descriptorVisibility.clear(); } readonly descriptorVisibility: Map = new Map(); - _pool?: boolean; } export class RenderPhaseData { @@ -784,7 +768,6 @@ export class RenderPhaseData { readonly shaderPrograms: ShaderProgramData[] = []; readonly shaderIndex: Map = new Map(); /*refcount*/ pipelineLayout: PipelineLayout | null = null; - _pool?: boolean; } //================================================================= @@ -1351,7 +1334,6 @@ export class LayoutGraphData implements BidirectionalGraph readonly shaderLayoutIndex: Map = new Map(); readonly effects: Map = new Map(); constantMacros = ''; - _pool?: boolean; } export class LayoutGraphObjectPoolSettings { @@ -1437,36 +1419,18 @@ export class LayoutGraphObjectPool { this._renderPhaseData.reset(); this._layoutGraphData.reset(); } - createDescriptorDB (isDebug = true): DescriptorDB { - let v: DescriptorDB; - if (isDebug) { - v = new DescriptorDB(); - } else { - v = this._descriptorDB.add(); - v._pool = true; - } + createDescriptorDB (): DescriptorDB { + const v = this._descriptorDB.add(); v.reset(); return v; } - createRenderPhase (isDebug = true): RenderPhase { - let v: RenderPhase; - if (isDebug) { - v = new RenderPhase(); - } else { - v = this._renderPhase.add(); - v._pool = true; - } + createRenderPhase (): RenderPhase { + const v = this._renderPhase.add(); v.reset(); return v; } - createLayoutGraph (isDebug = true): LayoutGraph { - let v: LayoutGraph; - if (isDebug) { - v = new LayoutGraph(); - } else { - v = this._layoutGraph.add(); - v._pool = true; - } + createLayoutGraph (): LayoutGraph { + const v = this._layoutGraph.add(); v.clear(); return v; } @@ -1474,26 +1438,13 @@ export class LayoutGraphObjectPool { uniformID = 0xFFFFFFFF, uniformType: Type = Type.UNKNOWN, offset = 0, - isDebug = true, ): UniformData { - let v: UniformData; - if (isDebug) { - v = new UniformData(); - } else { - v = this._uniformData.add(); - v._pool = true; - } + const v = this._uniformData.add(); v.reset(uniformID, uniformType, offset); return v; } - createUniformBlockData (isDebug = true): UniformBlockData { - let v: UniformBlockData; - if (isDebug) { - v = new UniformBlockData(); - } else { - v = this._uniformBlockData.add(); - v._pool = true; - } + createUniformBlockData (): UniformBlockData { + const v = this._uniformBlockData.add(); v.reset(); return v; } @@ -1501,15 +1452,8 @@ export class LayoutGraphObjectPool { descriptorID = 0, type: Type = Type.UNKNOWN, count = 1, - isDebug = true, ): DescriptorData { - let v: DescriptorData; - if (isDebug) { - v = new DescriptorData(); - } else { - v = this._descriptorData.add(); - v._pool = true; - } + const v = this._descriptorData.add(); v.reset(descriptorID, type, count); return v; } @@ -1517,144 +1461,69 @@ export class LayoutGraphObjectPool { type: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, capacity = 0, - isDebug = true, ): DescriptorBlockData { - let v: DescriptorBlockData; - if (isDebug) { - v = new DescriptorBlockData(); - } else { - v = this._descriptorBlockData.add(); - v._pool = true; - } + const v = this._descriptorBlockData.add(); v.reset(type, visibility, capacity); return v; } createDescriptorSetLayoutData ( slot = 0xFFFFFFFF, capacity = 0, - isDebug = true, ): DescriptorSetLayoutData { - let v: DescriptorSetLayoutData; - if (isDebug) { - v = new DescriptorSetLayoutData(); - } else { - v = this._descriptorSetLayoutData.add(); - v._pool = true; - } + const v = this._descriptorSetLayoutData.add(); v.reset(slot, capacity); return v; } createDescriptorSetData ( descriptorSetLayout: DescriptorSetLayout | null = null, descriptorSet: DescriptorSet | null = null, - isDebug = true, ): DescriptorSetData { - let v: DescriptorSetData; - if (isDebug) { - v = new DescriptorSetData(); - } else { - v = this._descriptorSetData.add(); - v._pool = true; - } + const v = this._descriptorSetData.add(); v.reset(descriptorSetLayout, descriptorSet); return v; } - createPipelineLayoutData (isDebug = true): PipelineLayoutData { - let v: PipelineLayoutData; - if (isDebug) { - v = new PipelineLayoutData(); - } else { - v = this._pipelineLayoutData.add(); - v._pool = true; - } + createPipelineLayoutData (): PipelineLayoutData { + const v = this._pipelineLayoutData.add(); v.reset(); return v; } - createShaderBindingData (isDebug = true): ShaderBindingData { - let v: ShaderBindingData; - if (isDebug) { - v = new ShaderBindingData(); - } else { - v = this._shaderBindingData.add(); - v._pool = true; - } + createShaderBindingData (): ShaderBindingData { + const v = this._shaderBindingData.add(); v.reset(); return v; } - createShaderLayoutData (isDebug = true): ShaderLayoutData { - let v: ShaderLayoutData; - if (isDebug) { - v = new ShaderLayoutData(); - } else { - v = this._shaderLayoutData.add(); - v._pool = true; - } + createShaderLayoutData (): ShaderLayoutData { + const v = this._shaderLayoutData.add(); v.reset(); return v; } - createTechniqueData (isDebug = true): TechniqueData { - let v: TechniqueData; - if (isDebug) { - v = new TechniqueData(); - } else { - v = this._techniqueData.add(); - v._pool = true; - } + createTechniqueData (): TechniqueData { + const v = this._techniqueData.add(); v.reset(); return v; } - createEffectData (isDebug = true): EffectData { - let v: EffectData; - if (isDebug) { - v = new EffectData(); - } else { - v = this._effectData.add(); - v._pool = true; - } + createEffectData (): EffectData { + const v = this._effectData.add(); v.reset(); return v; } - createShaderProgramData (isDebug = true): ShaderProgramData { - let v: ShaderProgramData; - if (isDebug) { - v = new ShaderProgramData(); - } else { - v = this._shaderProgramData.add(); - v._pool = true; - } + createShaderProgramData (): ShaderProgramData { + const v = this._shaderProgramData.add(); v.reset(); return v; } - createRenderStageData (isDebug = true): RenderStageData { - let v: RenderStageData; - if (isDebug) { - v = new RenderStageData(); - } else { - v = this._renderStageData.add(); - v._pool = true; - } + createRenderStageData (): RenderStageData { + const v = this._renderStageData.add(); v.reset(); return v; } - createRenderPhaseData (isDebug = true): RenderPhaseData { - let v: RenderPhaseData; - if (isDebug) { - v = new RenderPhaseData(); - } else { - v = this._renderPhaseData.add(); - v._pool = true; - } + createRenderPhaseData (): RenderPhaseData { + const v = this._renderPhaseData.add(); v.reset(); return v; } - createLayoutGraphData (isDebug = true): LayoutGraphData { - let v: LayoutGraphData; - if (isDebug) { - v = new LayoutGraphData(); - } else { - v = this._layoutGraphData.add(); - v._pool = true; - } + createLayoutGraphData (): LayoutGraphData { + const v = this._layoutGraphData.add(); v.clear(); return v; } @@ -1677,7 +1546,6 @@ export class LayoutGraphObjectPool { private readonly _renderStageData: RecyclePool; private readonly _renderPhaseData: RecyclePool; private readonly _layoutGraphData: RecyclePool; - public debug = false; } export function saveDescriptorDB (ar: OutputArchive, v: DescriptorDB): void { diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 0dcb547d86a..e97d787ff1f 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -179,7 +179,6 @@ export interface PipelineRuntime { * @zh 触发管线状态更新事件 */ onGlobalPipelineStateChanged (): void; - _pool?: boolean; } /** @@ -269,7 +268,6 @@ export enum SubpassCapabilities { */ export class PipelineCapabilities { subpass: SubpassCapabilities = SubpassCapabilities.NONE; - _pool?: boolean; } /** @@ -288,7 +286,6 @@ export interface RenderNode { * @experimental */ setCustomBehavior (name: string): void; - _pool?: boolean; } /** @@ -393,7 +390,6 @@ export interface Setter extends RenderNode { light: DirectionalLight, csmLevel?: number): void; setBuiltinSpotLightFrustumConstants (light: SpotLight): void; - _pool?: boolean; } export interface SceneBuilder extends Setter { @@ -401,7 +397,6 @@ export interface SceneBuilder extends Setter { light: Light, csmLevel?: number, optCamera?: Camera): void; - _pool?: boolean; } /** @@ -470,7 +465,6 @@ export interface RenderQueueBuilder extends Setter { * @experimental */ addCustomCommand (customBehavior: string): void; - _pool?: boolean; } /** @@ -565,7 +559,6 @@ export interface BasicRenderPassBuilder extends Setter { * @zh 在屏幕上渲染统计数据 */ showStatistics: boolean; - _pool?: boolean; } export interface BasicMultisampleRenderPassBuilder extends BasicRenderPassBuilder { @@ -575,7 +568,6 @@ export interface BasicMultisampleRenderPassBuilder extends BasicRenderPassBuilde target: string, depthMode?: ResolveMode, stencilMode?: ResolveMode): void; - _pool?: boolean; } /** @@ -824,7 +816,6 @@ export interface BasicPipeline extends PipelineRuntime { * @engineInternal */ getDescriptorSetLayout (shaderName: string, freq: UpdateFrequency): DescriptorSetLayout | undefined; - _pool?: boolean; } /** @@ -954,7 +945,6 @@ export interface RenderSubpassBuilder extends Setter { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; - _pool?: boolean; } /** @@ -983,7 +973,6 @@ export interface MultisampleRenderSubpassBuilder extends RenderSubpassBuilder { target: string, depthMode?: ResolveMode, stencilMode?: ResolveMode): void; - _pool?: boolean; } /** @@ -1006,7 +995,6 @@ export interface ComputeQueueBuilder extends Setter { threadGroupCountZ: number, material?: Material, passID?: number): void; - _pool?: boolean; } /** @@ -1090,7 +1078,6 @@ export interface ComputeSubpassBuilder extends Setter { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; - _pool?: boolean; } /** @@ -1161,7 +1148,6 @@ export interface RenderPassBuilder extends BasicRenderPassBuilder { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; - _pool?: boolean; } export interface MultisampleRenderPassBuilder extends BasicMultisampleRenderPassBuilder { @@ -1173,7 +1159,6 @@ export interface MultisampleRenderPassBuilder extends BasicMultisampleRenderPass name: string, accessType: AccessType, slotName: string): void; - _pool?: boolean; } /** @@ -1253,7 +1238,6 @@ export interface ComputePassBuilder extends Setter { * @experimental */ setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void; - _pool?: boolean; } /** @@ -1424,7 +1408,6 @@ export interface Pipeline extends BasicPipeline { name: string, info: TextureInfo, type: string): number; - _pool?: boolean; } /** @@ -1444,7 +1427,6 @@ export interface PipelineBuilder { */ setup (cameras: Camera[], pipeline: BasicPipeline): void; onGlobalPipelineStateChanged? (): void; - _pool?: boolean; } /** @@ -1454,5 +1436,4 @@ export interface RenderingModule { getPassID (name: string): number; getSubpassID (passID: number, name: string): number; getPhaseID (subpassOrPassID: number, name: string): number; - _pool?: boolean; } diff --git a/cocos/rendering/custom/private.ts b/cocos/rendering/custom/private.ts index 13566b9c74b..b4cae1f5d17 100644 --- a/cocos/rendering/custom/private.ts +++ b/cocos/rendering/custom/private.ts @@ -36,7 +36,6 @@ import { IProgramInfo } from '../../render-scene/core/program-lib'; export interface ProgramProxy { readonly name: string; readonly shader: Shader; - _pool?: boolean; } export interface ProgramLibrary { @@ -71,5 +70,4 @@ export interface ProgramLibrary { getProgramID (phaseID: number, programName: string): number; getDescriptorNameID (name: string): number; getDescriptorName (nameID: number): string; - _pool?: boolean; } diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 05b4e000448..135d22cd640 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -55,7 +55,6 @@ export class ClearValue { y: number; z: number; w: number; - _pool?: boolean; } export class RasterView { @@ -108,7 +107,6 @@ export class RasterView { readonly clearColor: Color; slotID = 0; shaderStageFlags: ShaderStageFlagBit; - _pool?: boolean; } export class ComputeView { @@ -149,7 +147,6 @@ export class ComputeView { clearValueType: ClearValueType; readonly clearValue: ClearValue; shaderStageFlags: ShaderStageFlagBit; - _pool?: boolean; } export class ResourceDesc { @@ -177,7 +174,6 @@ export class ResourceDesc { textureFlags: TextureFlagBit = TextureFlagBit.NONE; flags: ResourceFlags = ResourceFlags.NONE; viewType: TextureType = TextureType.TEX2D; - _pool?: boolean; } export class ResourceTraits { @@ -188,7 +184,6 @@ export class ResourceTraits { this.residency = residency; } residency: ResourceResidency; - _pool?: boolean; } export class RenderSwapchain { @@ -207,7 +202,6 @@ export class RenderSwapchain { currentID = 0; numBackBuffers = 0; generation = 0xFFFFFFFF; - _pool?: boolean; } export class ResourceStates { @@ -215,7 +209,6 @@ export class ResourceStates { this.states = AccessFlagBit.NONE; } states: AccessFlagBit = AccessFlagBit.NONE; - _pool?: boolean; } export class ManagedBuffer { @@ -228,7 +221,6 @@ export class ManagedBuffer { } /*refcount*/ buffer: Buffer | null; fenceValue = 0; - _pool?: boolean; } export class PersistentBuffer { @@ -241,7 +233,6 @@ export class PersistentBuffer { } /*refcount*/ buffer: Buffer | null; fenceValue = 0; - _pool?: boolean; } export class ManagedTexture { @@ -254,7 +245,6 @@ export class ManagedTexture { } /*refcount*/ texture: Texture | null; fenceValue = 0; - _pool?: boolean; } export class PersistentTexture { @@ -267,7 +257,6 @@ export class PersistentTexture { } /*refcount*/ texture: Texture | null; fenceValue = 0; - _pool?: boolean; } export class ManagedResource { @@ -275,7 +264,6 @@ export class ManagedResource { this.unused = 0; } unused = 0; - _pool?: boolean; } export class Subpass { @@ -287,7 +275,6 @@ export class Subpass { readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); readonly resolvePairs: ResolvePair[] = []; - _pool?: boolean; } //================================================================= @@ -589,7 +576,6 @@ export class SubpassGraph implements BidirectionalGraph readonly _vertices: SubpassGraphVertex[] = []; readonly _names: string[] = []; readonly _subpasses: Subpass[] = []; - _pool?: boolean; } export class RasterSubpass { @@ -616,7 +602,6 @@ export class RasterSubpass { count: number; quality: number; showStatistics = false; - _pool?: boolean; } export class ComputeSubpass { @@ -631,7 +616,6 @@ export class ComputeSubpass { readonly rasterViews: Map = new Map(); readonly computeViews: Map = new Map(); subpassID: number; - _pool?: boolean; } export class RasterPass { @@ -665,7 +649,6 @@ export class RasterPass { version = 0; hashValue = 0; showStatistics = false; - _pool?: boolean; } export class PersistentRenderPassAndFramebuffer { @@ -685,7 +668,6 @@ export class PersistentRenderPassAndFramebuffer { readonly clearColors: Color[] = []; clearDepth = 0; clearStencil = 0; - _pool?: boolean; } export class FormatView { @@ -693,7 +675,6 @@ export class FormatView { this.format = Format.UNKNOWN; } format: Format = Format.UNKNOWN; - _pool?: boolean; } export class SubresourceView { @@ -715,7 +696,6 @@ export class SubresourceView { numArraySlices = 0; firstPlane = 0; numPlanes = 0; - _pool?: boolean; } //================================================================= @@ -1467,7 +1447,6 @@ export class ResourceGraph implements BidirectionalGraph readonly renderPasses: Map = new Map(); nextFenceValue = 0; version = 0; - _pool?: boolean; } export class ComputePass { @@ -1477,7 +1456,6 @@ export class ComputePass { } readonly computeViews: Map = new Map(); readonly textures: Map = new Map(); - _pool?: boolean; } export class ResolvePass { @@ -1485,7 +1463,6 @@ export class ResolvePass { this.resolvePairs.length = 0; } readonly resolvePairs: ResolvePair[] = []; - _pool?: boolean; } export class CopyPass { @@ -1495,7 +1472,6 @@ export class CopyPass { } readonly copyPairs: CopyPair[] = []; readonly uploadPairs: UploadPair[] = []; - _pool?: boolean; } export class MovePass { @@ -1503,7 +1479,6 @@ export class MovePass { this.movePairs.length = 0; } readonly movePairs: MovePair[] = []; - _pool?: boolean; } export class RaytracePass { @@ -1511,7 +1486,6 @@ export class RaytracePass { this.computeViews.clear(); } readonly computeViews: Map = new Map(); - _pool?: boolean; } export class ClearView { @@ -1528,7 +1502,6 @@ export class ClearView { slotName: string; clearFlags: ClearFlagBit; readonly clearColor: Color; - _pool?: boolean; } export class RenderQueue { @@ -1544,7 +1517,6 @@ export class RenderQueue { hint: QueueHint; phaseID: number; viewport: Viewport | null = null; - _pool?: boolean; } export enum CullingFlags { @@ -1590,7 +1562,6 @@ export class SceneData { flags: SceneFlags; cullingFlags: CullingFlags; /*refcount*/ shadingLight: Light | null; - _pool?: boolean; } export class Dispatch { @@ -1625,7 +1596,6 @@ export class Dispatch { threadGroupCountX: number; threadGroupCountY: number; threadGroupCountZ: number; - _pool?: boolean; } export class Blit { @@ -1645,7 +1615,6 @@ export class Blit { passID: number; sceneFlags: SceneFlags; /*pointer*/ camera: Camera | null; - _pool?: boolean; } export class RenderData { @@ -1661,7 +1630,6 @@ export class RenderData { readonly textures: Map = new Map(); readonly samplers: Map = new Map(); custom = ''; - _pool?: boolean; } //================================================================= @@ -2546,7 +2514,6 @@ export class RenderGraph implements BidirectionalGraph readonly _valid: boolean[] = []; readonly index: Map = new Map(); readonly sortedVertices: number[] = []; - _pool?: boolean; } export class RenderGraphObjectPoolSettings { @@ -2697,15 +2664,8 @@ export class RenderGraphObjectPool { y = 0, z = 0, w = 0, - isDebug = true, ): ClearValue { - let v: ClearValue; - if (isDebug) { - v = new ClearValue(); - } else { - v = this._clearValue.add(); - v._pool = true; - } + const v = this._clearValue.add(); v.reset(x, y, z, w); return v; } @@ -2717,15 +2677,8 @@ export class RenderGraphObjectPool { storeOp: StoreOp = StoreOp.STORE, clearFlags: ClearFlagBit = ClearFlagBit.ALL, shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, - isDebug = true, ): RasterView { - let v: RasterView; - if (isDebug) { - v = new RasterView(); - } else { - v = this._rasterView.add(); - v._pool = true; - } + const v = this._rasterView.add(); v.reset(slotName, accessType, attachmentType, loadOp, storeOp, clearFlags, shaderStageFlags); return v; } @@ -2735,154 +2688,75 @@ export class RenderGraphObjectPool { clearFlags: ClearFlagBit = ClearFlagBit.NONE, clearValueType: ClearValueType = ClearValueType.NONE, shaderStageFlags: ShaderStageFlagBit = ShaderStageFlagBit.NONE, - isDebug = true, ): ComputeView { - let v: ComputeView; - if (isDebug) { - v = new ComputeView(); - } else { - v = this._computeView.add(); - v._pool = true; - } + const v = this._computeView.add(); v.reset(name, accessType, clearFlags, clearValueType, shaderStageFlags); return v; } - createResourceDesc (isDebug = true): ResourceDesc { - let v: ResourceDesc; - if (isDebug) { - v = new ResourceDesc(); - } else { - v = this._resourceDesc.add(); - v._pool = true; - } + createResourceDesc (): ResourceDesc { + const v = this._resourceDesc.add(); v.reset(); return v; } createResourceTraits ( residency: ResourceResidency = ResourceResidency.MANAGED, - isDebug = true, ): ResourceTraits { - let v: ResourceTraits; - if (isDebug) { - v = new ResourceTraits(); - } else { - v = this._resourceTraits.add(); - v._pool = true; - } + const v = this._resourceTraits.add(); v.reset(residency); return v; } createRenderSwapchain ( swapchain: Swapchain | null = null, - isDebug = true, ): RenderSwapchain { - let v: RenderSwapchain; - if (isDebug) { - v = new RenderSwapchain(); - } else { - v = this._renderSwapchain.add(); - v._pool = true; - } + const v = this._renderSwapchain.add(); v.reset(swapchain); return v; } - createResourceStates (isDebug = true): ResourceStates { - let v: ResourceStates; - if (isDebug) { - v = new ResourceStates(); - } else { - v = this._resourceStates.add(); - v._pool = true; - } + createResourceStates (): ResourceStates { + const v = this._resourceStates.add(); v.reset(); return v; } createManagedBuffer ( buffer: Buffer | null = null, - isDebug = true, ): ManagedBuffer { - let v: ManagedBuffer; - if (isDebug) { - v = new ManagedBuffer(); - } else { - v = this._managedBuffer.add(); - v._pool = true; - } + const v = this._managedBuffer.add(); v.reset(buffer); return v; } createPersistentBuffer ( buffer: Buffer | null = null, - isDebug = true, ): PersistentBuffer { - let v: PersistentBuffer; - if (isDebug) { - v = new PersistentBuffer(); - } else { - v = this._persistentBuffer.add(); - v._pool = true; - } + const v = this._persistentBuffer.add(); v.reset(buffer); return v; } createManagedTexture ( texture: Texture | null = null, - isDebug = true, ): ManagedTexture { - let v: ManagedTexture; - if (isDebug) { - v = new ManagedTexture(); - } else { - v = this._managedTexture.add(); - v._pool = true; - } + const v = this._managedTexture.add(); v.reset(texture); return v; } createPersistentTexture ( texture: Texture | null = null, - isDebug = true, ): PersistentTexture { - let v: PersistentTexture; - if (isDebug) { - v = new PersistentTexture(); - } else { - v = this._persistentTexture.add(); - v._pool = true; - } + const v = this._persistentTexture.add(); v.reset(texture); return v; } - createManagedResource (isDebug = true): ManagedResource { - let v: ManagedResource; - if (isDebug) { - v = new ManagedResource(); - } else { - v = this._managedResource.add(); - v._pool = true; - } + createManagedResource (): ManagedResource { + const v = this._managedResource.add(); v.reset(); return v; } - createSubpass (isDebug = true): Subpass { - let v: Subpass; - if (isDebug) { - v = new Subpass(); - } else { - v = this._subpass.add(); - v._pool = true; - } + createSubpass (): Subpass { + const v = this._subpass.add(); v.reset(); return v; } - createSubpassGraph (isDebug = true): SubpassGraph { - let v: SubpassGraph; - if (isDebug) { - v = new SubpassGraph(); - } else { - v = this._subpassGraph.add(); - v._pool = true; - } + createSubpassGraph (): SubpassGraph { + const v = this._subpassGraph.add(); v.clear(); return v; } @@ -2890,173 +2764,84 @@ export class RenderGraphObjectPool { subpassID = 0xFFFFFFFF, count = 1, quality = 0, - isDebug = true, ): RasterSubpass { - let v: RasterSubpass; - if (isDebug) { - v = new RasterSubpass(); - } else { - v = this._rasterSubpass.add(); - v._pool = true; - } + const v = this._rasterSubpass.add(); v.reset(subpassID, count, quality); return v; } createComputeSubpass ( subpassID = 0xFFFFFFFF, - isDebug = true, ): ComputeSubpass { - let v: ComputeSubpass; - if (isDebug) { - v = new ComputeSubpass(); - } else { - v = this._computeSubpass.add(); - v._pool = true; - } + const v = this._computeSubpass.add(); v.reset(subpassID); return v; } - createRasterPass (isDebug = true): RasterPass { - let v: RasterPass; - if (isDebug) { - v = new RasterPass(); - } else { - v = this._rasterPass.add(); - v._pool = true; - } + createRasterPass (): RasterPass { + const v = this._rasterPass.add(); v.reset(); return v; } createPersistentRenderPassAndFramebuffer ( renderPass: RenderPass | null = null, framebuffer: Framebuffer | null = null, - isDebug = true, ): PersistentRenderPassAndFramebuffer { - let v: PersistentRenderPassAndFramebuffer; - if (isDebug) { - v = new PersistentRenderPassAndFramebuffer(); - } else { - v = this._persistentRenderPassAndFramebuffer.add(); - v._pool = true; - } + const v = this._persistentRenderPassAndFramebuffer.add(); v.reset(renderPass, framebuffer); return v; } - createFormatView (isDebug = true): FormatView { - let v: FormatView; - if (isDebug) { - v = new FormatView(); - } else { - v = this._formatView.add(); - v._pool = true; - } + createFormatView (): FormatView { + const v = this._formatView.add(); v.reset(); return v; } - createSubresourceView (isDebug = true): SubresourceView { - let v: SubresourceView; - if (isDebug) { - v = new SubresourceView(); - } else { - v = this._subresourceView.add(); - v._pool = true; - } + createSubresourceView (): SubresourceView { + const v = this._subresourceView.add(); v.reset(); return v; } - createResourceGraph (isDebug = true): ResourceGraph { - let v: ResourceGraph; - if (isDebug) { - v = new ResourceGraph(); - } else { - v = this._resourceGraph.add(); - v._pool = true; - } + createResourceGraph (): ResourceGraph { + const v = this._resourceGraph.add(); v.clear(); return v; } - createComputePass (isDebug = true): ComputePass { - let v: ComputePass; - if (isDebug) { - v = new ComputePass(); - } else { - v = this._computePass.add(); - v._pool = true; - } + createComputePass (): ComputePass { + const v = this._computePass.add(); v.reset(); return v; } - createResolvePass (isDebug = true): ResolvePass { - let v: ResolvePass; - if (isDebug) { - v = new ResolvePass(); - } else { - v = this._resolvePass.add(); - v._pool = true; - } + createResolvePass (): ResolvePass { + const v = this._resolvePass.add(); v.reset(); return v; } - createCopyPass (isDebug = true): CopyPass { - let v: CopyPass; - if (isDebug) { - v = new CopyPass(); - } else { - v = this._copyPass.add(); - v._pool = true; - } + createCopyPass (): CopyPass { + const v = this._copyPass.add(); v.reset(); return v; } - createMovePass (isDebug = true): MovePass { - let v: MovePass; - if (isDebug) { - v = new MovePass(); - } else { - v = this._movePass.add(); - v._pool = true; - } + createMovePass (): MovePass { + const v = this._movePass.add(); v.reset(); return v; } - createRaytracePass (isDebug = true): RaytracePass { - let v: RaytracePass; - if (isDebug) { - v = new RaytracePass(); - } else { - v = this._raytracePass.add(); - v._pool = true; - } + createRaytracePass (): RaytracePass { + const v = this._raytracePass.add(); v.reset(); return v; } createClearView ( slotName = '', clearFlags: ClearFlagBit = ClearFlagBit.ALL, - isDebug = true, ): ClearView { - let v: ClearView; - if (isDebug) { - v = new ClearView(); - } else { - v = this._clearView.add(); - v._pool = true; - } + const v = this._clearView.add(); v.reset(slotName, clearFlags); return v; } createRenderQueue ( hint: QueueHint = QueueHint.RENDER_OPAQUE, phaseID = 0xFFFFFFFF, - isDebug = true, ): RenderQueue { - let v: RenderQueue; - if (isDebug) { - v = new RenderQueue(); - } else { - v = this._renderQueue.add(); - v._pool = true; - } + const v = this._renderQueue.add(); v.reset(hint, phaseID); return v; } @@ -3066,15 +2851,8 @@ export class RenderGraphObjectPool { flags: SceneFlags = SceneFlags.NONE, cullingFlags: CullingFlags = CullingFlags.CAMERA_FRUSTUM, shadingLight: Light | null = null, - isDebug = true, ): SceneData { - let v: SceneData; - if (isDebug) { - v = new SceneData(); - } else { - v = this._sceneData.add(); - v._pool = true; - } + const v = this._sceneData.add(); v.reset(scene, camera, flags, cullingFlags, shadingLight); return v; } @@ -3084,15 +2862,8 @@ export class RenderGraphObjectPool { threadGroupCountX = 0, threadGroupCountY = 0, threadGroupCountZ = 0, - isDebug = true, ): Dispatch { - let v: Dispatch; - if (isDebug) { - v = new Dispatch(); - } else { - v = this._dispatch.add(); - v._pool = true; - } + const v = this._dispatch.add(); v.reset(material, passID, threadGroupCountX, threadGroupCountY, threadGroupCountZ); return v; } @@ -3101,37 +2872,18 @@ export class RenderGraphObjectPool { passID = 0, sceneFlags: SceneFlags = SceneFlags.NONE, camera: Camera | null = null, - isDebug = true, ): Blit { - let v: Blit; - if (isDebug) { - v = new Blit(); - } else { - v = this._blit.add(); - v._pool = true; - } + const v = this._blit.add(); v.reset(material, passID, sceneFlags, camera); return v; } - createRenderData (isDebug = true): RenderData { - let v: RenderData; - if (isDebug) { - v = new RenderData(); - } else { - v = this._renderData.add(); - v._pool = true; - } + createRenderData (): RenderData { + const v = this._renderData.add(); v.reset(); return v; } - createRenderGraph (isDebug = true): RenderGraph { - let v: RenderGraph; - if (isDebug) { - v = new RenderGraph(); - } else { - v = this._renderGraph.add(); - v._pool = true; - } + createRenderGraph (): RenderGraph { + const v = this._renderGraph.add(); v.clear(); return v; } @@ -3169,5 +2921,4 @@ export class RenderGraphObjectPool { private readonly _blit: RecyclePool; private readonly _renderData: RecyclePool; private readonly _renderGraph: RecyclePool; - public debug = false; } diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index 21ac51db9ba..577955e8017 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -307,7 +307,6 @@ export class LightInfo { /*pointer*/ probe: ReflectionProbe | null; level: number; culledByLight: boolean; - _pool?: boolean; } export enum DescriptorTypeOrder { @@ -357,7 +356,6 @@ export class Descriptor { } type: Type; count = 1; - _pool?: boolean; } export class DescriptorBlock { @@ -371,7 +369,6 @@ export class DescriptorBlock { readonly uniformBlocks: Map = new Map(); capacity = 0; count = 0; - _pool?: boolean; } export class DescriptorBlockFlattened { @@ -389,7 +386,6 @@ export class DescriptorBlockFlattened { readonly uniformBlocks: UniformBlock[] = []; capacity = 0; count = 0; - _pool?: boolean; } export class DescriptorBlockIndex { @@ -403,7 +399,6 @@ export class DescriptorBlockIndex { parameterType: ParameterType; descriptorType: DescriptorTypeOrder; visibility: ShaderStageFlagBit; - _pool?: boolean; } export enum ResolveFlags { @@ -445,7 +440,6 @@ export class ResolvePair { resolveFlags: ResolveFlags; mode: ResolveMode; mode1: ResolveMode; - _pool?: boolean; } export class CopyPair { @@ -505,7 +499,6 @@ export class CopyPair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; - _pool?: boolean; } export class UploadPair { @@ -549,7 +542,6 @@ export class UploadPair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; - _pool?: boolean; } export class MovePair { @@ -594,7 +586,6 @@ export class MovePair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; - _pool?: boolean; } export class PipelineStatistics { @@ -622,7 +613,6 @@ export class PipelineStatistics { numFreeDescriptorSets = 0; numInstancingBuffers = 0; numInstancingUniformBlocks = 0; - _pool?: boolean; } export class RenderCommonObjectPoolSettings { @@ -680,51 +670,25 @@ export class RenderCommonObjectPool { level = 0, culledByLight = false, probe: ReflectionProbe | null = null, - isDebug = true, ): LightInfo { - let v: LightInfo; - if (isDebug) { - v = new LightInfo(); - } else { - v = this._lightInfo.add(); - v._pool = true; - } + const v = this._lightInfo.add(); v.reset(light, level, culledByLight, probe); return v; } createDescriptor ( type: Type = Type.UNKNOWN, - isDebug = true, ): Descriptor { - let v: Descriptor; - if (isDebug) { - v = new Descriptor(); - } else { - v = this._descriptor.add(); - v._pool = true; - } + const v = this._descriptor.add(); v.reset(type); return v; } - createDescriptorBlock (isDebug = true): DescriptorBlock { - let v: DescriptorBlock; - if (isDebug) { - v = new DescriptorBlock(); - } else { - v = this._descriptorBlock.add(); - v._pool = true; - } + createDescriptorBlock (): DescriptorBlock { + const v = this._descriptorBlock.add(); v.reset(); return v; } - createDescriptorBlockFlattened (isDebug = true): DescriptorBlockFlattened { - let v: DescriptorBlockFlattened; - if (isDebug) { - v = new DescriptorBlockFlattened(); - } else { - v = this._descriptorBlockFlattened.add(); - v._pool = true; - } + createDescriptorBlockFlattened (): DescriptorBlockFlattened { + const v = this._descriptorBlockFlattened.add(); v.reset(); return v; } @@ -733,15 +697,8 @@ export class RenderCommonObjectPool { parameterType: ParameterType = ParameterType.CONSTANTS, descriptorType: DescriptorTypeOrder = DescriptorTypeOrder.UNIFORM_BUFFER, visibility: ShaderStageFlagBit = ShaderStageFlagBit.NONE, - isDebug = true, ): DescriptorBlockIndex { - let v: DescriptorBlockIndex; - if (isDebug) { - v = new DescriptorBlockIndex(); - } else { - v = this._descriptorBlockIndex.add(); - v._pool = true; - } + const v = this._descriptorBlockIndex.add(); v.updateFrequency = updateFrequency; v.parameterType = parameterType; v.descriptorType = descriptorType; @@ -754,15 +711,8 @@ export class RenderCommonObjectPool { resolveFlags: ResolveFlags = ResolveFlags.NONE, mode: ResolveMode = ResolveMode.SAMPLE_ZERO, mode1: ResolveMode = ResolveMode.SAMPLE_ZERO, - isDebug = true, ): ResolvePair { - let v: ResolvePair; - if (isDebug) { - v = new ResolvePair(); - } else { - v = this._resolvePair.add(); - v._pool = true; - } + const v = this._resolvePair.add(); v.reset(source, target, resolveFlags, mode, mode1); return v; } @@ -777,15 +727,8 @@ export class RenderCommonObjectPool { targetMostDetailedMip = 0, targetFirstSlice = 0, targetPlaneSlice = 0, - isDebug = true, ): CopyPair { - let v: CopyPair; - if (isDebug) { - v = new CopyPair(); - } else { - v = this._copyPair.add(); - v._pool = true; - } + const v = this._copyPair.add(); v.reset(source, target, mipLevels, numSlices, sourceMostDetailedMip, sourceFirstSlice, sourcePlaneSlice, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } @@ -796,15 +739,8 @@ export class RenderCommonObjectPool { targetMostDetailedMip = 0, targetFirstSlice = 0, targetPlaneSlice = 0, - isDebug = true, ): UploadPair { - let v: UploadPair; - if (isDebug) { - v = new UploadPair(); - } else { - v = this._uploadPair.add(); - v._pool = true; - } + const v = this._uploadPair.add(); v.reset(target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } @@ -816,26 +752,13 @@ export class RenderCommonObjectPool { targetMostDetailedMip = 0, targetFirstSlice = 0, targetPlaneSlice = 0, - isDebug = true, ): MovePair { - let v: MovePair; - if (isDebug) { - v = new MovePair(); - } else { - v = this._movePair.add(); - v._pool = true; - } + const v = this._movePair.add(); v.reset(source, target, mipLevels, numSlices, targetMostDetailedMip, targetFirstSlice, targetPlaneSlice); return v; } - createPipelineStatistics (isDebug = true): PipelineStatistics { - let v: PipelineStatistics; - if (isDebug) { - v = new PipelineStatistics(); - } else { - v = this._pipelineStatistics.add(); - v._pool = true; - } + createPipelineStatistics (): PipelineStatistics { + const v = this._pipelineStatistics.add(); v.reset(); return v; } @@ -849,7 +772,6 @@ export class RenderCommonObjectPool { private readonly _uploadPair: RecyclePool; private readonly _movePair: RecyclePool; private readonly _pipelineStatistics: RecyclePool; - public debug = false; } export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { diff --git a/cocos/rendering/custom/web-types.ts b/cocos/rendering/custom/web-types.ts index 1760987eb42..b275b9abde9 100644 --- a/cocos/rendering/custom/web-types.ts +++ b/cocos/rendering/custom/web-types.ts @@ -51,11 +51,9 @@ export class ProgramInfo { readonly attributes: Attribute[]; readonly blockSizes: number[]; readonly handleMap: Record; - _pool?: boolean; } export class ProgramGroup { readonly programInfos: Map = new Map(); readonly programProxies: Map = new Map(); - _pool?: boolean; } From 3da6495497a7e49d3cf2b90a810db817a3361099 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Thu, 21 Sep 2023 16:03:57 +0800 Subject: [PATCH 70/82] revert version --- editor/assets/primitives.fbx.meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/assets/primitives.fbx.meta b/editor/assets/primitives.fbx.meta index fdc6e41562b..ea556cdb69f 100644 --- a/editor/assets/primitives.fbx.meta +++ b/editor/assets/primitives.fbx.meta @@ -1,5 +1,5 @@ { - "ver": "2.3.12", + "ver": "2.3.8", "importer": "fbx", "imported": true, "uuid": "1263d74c-8167-4928-91a6-4e2672411f47", From 04a782d7c9efc4fa592bbbc5efeb330e67924552 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 21 Sep 2023 17:38:41 +0800 Subject: [PATCH 71/82] Complete the webpipeline pool (#177) --- cocos/rendering/custom/executor.ts | 19 +- cocos/rendering/custom/web-pipeline.ts | 348 ++++++++++++++++++------- 2 files changed, 255 insertions(+), 112 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 15e01ec16d3..e2567007219 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -248,26 +248,11 @@ class DeviceTexture extends DeviceResource { get description (): ResourceDesc | null { return this._desc; } get trait (): ResourceTraits | null { return this._trait; } get swapchain (): Swapchain | null { return this._swapchain; } - private _setDesc (desc: ResourceDesc): void { - if (!this._desc) { - this._desc = new ResourceDesc(); - } - this._desc.alignment = desc.alignment; - this._desc.depthOrArraySize = desc.depthOrArraySize; - this._desc.dimension = desc.dimension; - this._desc.flags = desc.flags; - this._desc.format = desc.format; - this._desc.height = desc.height; - this._desc.mipLevels = desc.mipLevels; - this._desc.sampleCount = desc.sampleCount; - this._desc.textureFlags = desc.textureFlags; - this._desc.width = desc.width; - } constructor (name: string, tex: PersistentTexture | Framebuffer | RenderSwapchain | ManagedResource) { super(name); const resGraph = context.resourceGraph; const verID = resGraph.vertex(name); - this._setDesc(resGraph.getDesc(verID)); + this._desc = resGraph.getDesc(verID); this._trait = resGraph.getTraits(verID); if (tex instanceof Texture) { this._texture = tex; @@ -282,7 +267,7 @@ class DeviceTexture extends DeviceResource { return; } - const info = this._desc!; + const info = this._desc; let type = TextureType.TEX2D; switch (info.dimension) { diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index ac65bfd8e2d..528af286564 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -25,10 +25,10 @@ /* eslint-disable max-len */ import { systemInfo } from 'pal/system-info'; import { DEBUG, EDITOR } from 'internal:constants'; -import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, Sampler, Swapchain, Texture, ClearFlagBit, DescriptorSet, deviceManager, Viewport, API, CommandBuffer, Type, SamplerInfo, Filter, Address, DescriptorSetInfo, LoadOp, StoreOp, ShaderStageFlagBit, BufferInfo, TextureInfo, TextureType, UniformBlock, ResolveMode, SampleCount, Color } from '../../gfx'; -import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; -import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency, UploadPair } from './types'; -import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass, PersistentBuffer } from './render-graph'; +import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, Sampler, Swapchain, Texture, ClearFlagBit, DescriptorSet, deviceManager, Viewport, API, CommandBuffer, Type, SamplerInfo, Filter, Address, DescriptorSetInfo, LoadOp, StoreOp, ShaderStageFlagBit, BufferInfo, TextureInfo, TextureType, UniformBlock, ResolveMode, SampleCount, Color, ComparisonFunc } from '../../gfx'; +import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor, RecyclePool } from '../../core'; +import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, RenderCommonObjectPool, RenderCommonObjectPoolSettings, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency, UploadPair } from './types'; +import { ComputePass, CopyPass, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass, PersistentBuffer, RenderGraphObjectPool, RenderGraphObjectPoolSettings, CullingFlags, ManagedResource, ManagedBuffer } from './render-graph'; import { ComputePassBuilder, ComputeQueueBuilder, BasicPipeline, PipelineBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder, Setter, SceneBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight, ProbeType } from '../../render-scene/scene'; @@ -58,6 +58,7 @@ import { CSMLayers, CSMShadowLayer } from '../shadow/csm-layers'; import { Scene } from '../../scene-graph'; import { Director } from '../../game'; import { ReflectionProbeManager } from '../../3d'; +import { legacyCC } from '../../core/global-exports'; const _uboVec = new Vec4(); const _uboVec3 = new Vec3(); @@ -73,6 +74,83 @@ const _samplerPointInfo = new SamplerInfo( Address.CLAMP, Address.CLAMP, ); + +const renderCommonObjectSetting = new RenderCommonObjectPoolSettings(16); +const renderGraphPoolSetting: RenderGraphObjectPoolSettings = new RenderGraphObjectPoolSettings(16); +class PipelinePool { + renderData = new RenderData(); + layoutGraph = new LayoutGraphData(); + rg = new RenderGraph(); + vertId = -1; + sceneData = new SceneData(); + resourceGraph = new ResourceGraph(); + computePass = new ComputePass(); + rasterPass = new RasterPass(); + rasterSubpass = new RasterSubpass(); + renderQueue = new RenderQueue(); + sceneBuilder = new RecyclePool(() => new WebSceneBuilder(this.renderData, this.layoutGraph, this.rg, this.vertId, this.sceneData), 16); + renderPassBuilder = new RecyclePool(() => new WebRenderPassBuilder(this.renderData, this.rg, this.layoutGraph, this.resourceGraph, this.vertId, this.rasterPass, this.getPipelineSceneData()), 16); + computeQueueBuilder = new RecyclePool(() => new WebComputeQueueBuilder(this.renderData, this.rg, this.layoutGraph, this.vertId, this.renderQueue, this.getPipelineSceneData()), 16); + renderQueueBuilder = new RecyclePool(() => new WebRenderQueueBuilder(this.renderData, this.rg, this.layoutGraph, this.vertId, this.renderQueue, this.getPipelineSceneData()), 16); + renderSubpassBuilder = new RecyclePool(() => new WebRenderSubpassBuilder(this.renderData, this.rg, this.layoutGraph, this.vertId, this.rasterSubpass, this.getPipelineSceneData()), 16); + computePassBuilder = new RecyclePool(() => new WebComputePassBuilder(this.renderData, this.rg, this.layoutGraph, this.resourceGraph, this.vertId, this.computePass, this.getPipelineSceneData()), 16); + samplerInfo = new RecyclePool(() => new SamplerInfo(), 16); + color = new RecyclePool(() => new Color(), 16); + renderCommonObjectPool = new RenderCommonObjectPool(renderCommonObjectSetting); + renderGraphPool = new RenderGraphObjectPool(renderGraphPoolSetting, this.renderCommonObjectPool); + viewport = new RecyclePool(() => new Viewport(), 16); + + getPipelineSceneData (): PipelineSceneData { + return (legacyCC.director.root as Root).pipeline.pipelineSceneData; + } + + createColor ( + x: number = 0, + y: number = 0, + z: number = 0, + w: number = 0, + ): Color { + const color = this.color.add(); + color.set(x, y, z, w); + return color; + } + createSamplerInfo ( + minFilter: Filter = Filter.LINEAR, + magFilter: Filter = Filter.LINEAR, + mipFilter: Filter = Filter.NONE, + addressU: Address = Address.WRAP, + addressV: Address = Address.WRAP, + addressW: Address = Address.WRAP, + maxAnisotropy: number = 0, + cmpFunc: ComparisonFunc = ComparisonFunc.ALWAYS, + ): SamplerInfo { + const samplerInfo = this.samplerInfo.add(); + samplerInfo.minFilter = minFilter; + samplerInfo.magFilter = magFilter; + samplerInfo.mipFilter = mipFilter; + samplerInfo.addressU = addressU; + samplerInfo.addressV = addressV; + samplerInfo.addressW = addressW; + samplerInfo.maxAnisotropy = maxAnisotropy; + samplerInfo.cmpFunc = cmpFunc; + return samplerInfo; + } + reset (): void { + this.sceneBuilder.reset(); + this.renderPassBuilder.reset(); + this.computePassBuilder.reset(); + this.computeQueueBuilder.reset(); + this.renderCommonObjectPool.reset(); + this.renderGraphPool.reset(); + this.viewport.reset(); + this.samplerInfo.reset(); + this.color.reset(); + this.renderQueueBuilder.reset(); + this.renderSubpassBuilder.reset(); + } +} +let pipelinePool: PipelinePool; +let renderGraphPool: RenderGraphObjectPool; export class WebSetter implements Setter { constructor (data: RenderData, lg: LayoutGraphData) { this._data = data; @@ -892,6 +970,20 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder { this._scene = scene; this._sceneId = sceneId; } + update ( + data: RenderData, + layoutGraph: LayoutGraphData, + rg: RenderGraph, + sceneId: number, + scene: SceneData, + ): void { + this._data = data; + this._lg = layoutGraph; + this._renderGraph = rg; + this._scene = scene; + this._sceneId = sceneId; + } + useLightFrustum (light: Light, csmLevel = 0, optCamera: Camera | undefined = undefined): void { this._scene.light.light = light; this._scene.light.level = csmLevel; @@ -907,9 +999,9 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder { const layoutName = this._renderGraph.getLayout(passId); setShadowUBOLightView(this, this._scene.camera!, light, csmLevel, layoutName); } - private readonly _renderGraph: RenderGraph; - private readonly _scene: SceneData; - private readonly _sceneId: number; + private _renderGraph: RenderGraph; + private _scene: SceneData; + private _sceneId: number; } export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuilder { @@ -920,6 +1012,15 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild this._queue = queue; this._pipeline = pipeline; } + update (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, vertID: number, queue: RenderQueue, pipeline: PipelineSceneData): void { + this._data = data; + this._lg = layoutGraph; + this._renderGraph = renderGraph; + this._vertID = vertID; + this._queue = queue; + this._pipeline = pipeline; + } + setArrayBuffer (name: string, arrayBuffer: ArrayBuffer): void { throw new Error('Method not implemented.'); } @@ -937,8 +1038,8 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild } addSceneOfCamera (camera: Camera, light: LightInfo, sceneFlags = SceneFlags.NONE, name = 'Camera'): void { - const sceneData = new SceneData(camera.scene, camera, sceneFlags, light); - this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, name, '', new RenderData(), false, this._vertID); + const sceneData = renderGraphPool.createSceneData(camera.scene, camera, sceneFlags, CullingFlags.NONE, light.light); + this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, name, '', renderGraphPool.createRenderData(), false, this._vertID); const layoutName = this.getLayoutName(); const scene: Scene = cclegacy.director.getScene(); setCameraUBOValues( @@ -957,11 +1058,11 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild initGlobalDescBinding(this._data, layoutName); } addScene (camera: Camera, sceneFlags = SceneFlags.NONE, light: Light | undefined = undefined): SceneBuilder { - const sceneData = new SceneData(camera.scene, camera, sceneFlags); + const sceneData = renderGraphPool.createSceneData(camera.scene, camera, sceneFlags); if (light) { sceneData.light.light = light; } - const renderData = new RenderData(); + const renderData = renderGraphPool.createRenderData(); const sceneId = this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); if (!(sceneFlags & SceneFlags.NON_BUILTIN)) { const layoutName = this.getLayoutName(); @@ -976,15 +1077,17 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild setTextureUBOView(this, camera, this._pipeline); initGlobalDescBinding(this._data, layoutName); } - return new WebSceneBuilder(renderData, this._lg, this._renderGraph, sceneId, sceneData); + const sceneBuilder = pipelinePool.sceneBuilder.add(); + sceneBuilder.update(renderData, this._lg, this._renderGraph, sceneId, sceneData); + return sceneBuilder; } addFullscreenQuad (material: Material, passID: number, sceneFlags = SceneFlags.NONE, name = 'Quad'): void { this._renderGraph.addVertex( RenderGraphValue.Blit, - new Blit(material, passID, sceneFlags, null), + renderGraphPool.createBlit(material, passID, sceneFlags, null), name, '', - new RenderData(), + renderGraphPool.createRenderData(), false, this._vertID, ); @@ -1008,10 +1111,10 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild addCameraQuad (camera: Camera, material: Material, passID: number, sceneFlags = SceneFlags.NONE): void { this._renderGraph.addVertex( RenderGraphValue.Blit, - new Blit(material, passID, sceneFlags, camera), + renderGraphPool.createBlit(material, passID, sceneFlags, camera), 'CameraQuad', '', - new RenderData(), + renderGraphPool.createRenderData(), false, this._vertID, ); @@ -1033,18 +1136,21 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild initGlobalDescBinding(this._data, layoutName); } clearRenderTarget (name: string, color: Color = new Color()): void { + const clearView = renderGraphPool.createClearView(name, ClearFlagBit.COLOR); + clearView.clearColor.copy(color); this._renderGraph.addVertex( RenderGraphValue.Clear, - [new ClearView(name, ClearFlagBit.COLOR, color)], + [clearView], 'ClearRenderTarget', '', - new RenderData(), + renderGraphPool.createRenderData(), false, this._vertID, ); } setViewport (viewport: Viewport): void { - this._queue.viewport = new Viewport().copy(viewport); + const currViewport = pipelinePool.viewport.add(); + this._queue.viewport = currViewport.copy(viewport); } addCustomCommand (customBehavior: string): void { throw new Error('Method not implemented.'); @@ -1066,7 +1172,24 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB ) { super(data, layoutGraph); this._renderGraph = renderGraph; - this._layoutGraph = layoutGraph; + this._vertID = vertID; + this._subpass = subpass; + this._pipeline = pipeline; + + const layoutName = this._renderGraph.component(RenderGraphComponent.Layout, this._vertID); + this._layoutID = layoutGraph.locateChild(layoutGraph.nullVertex(), layoutName); + } + update ( + data: RenderData, + renderGraph: RenderGraph, + layoutGraph: LayoutGraphData, + vertID: number, + subpass: RasterSubpass, + pipeline: PipelineSceneData, + ): void { + this._data = data; + this._lg = layoutGraph; + this._renderGraph = renderGraph; this._vertID = vertID; this._subpass = subpass; this._pipeline = pipeline; @@ -1106,15 +1229,16 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB throw new Error('Method not implemented.'); } addQueue (hint: QueueHint = QueueHint.RENDER_OPAQUE, layoutName = 'default'): RenderQueueBuilder { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); + const layoutId = this._lg.locateChild(this._layoutID, layoutName); if (DEBUG) { assert(layoutId !== 0xFFFFFFFF); } - const queue = new RenderQueue(hint); - queue.phaseID = layoutId; - const data = new RenderData(); + const queue = renderGraphPool.createRenderQueue(hint, layoutId); + const data = renderGraphPool.createRenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); - return new WebRenderQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); + const queueBuilder = pipelinePool.renderQueueBuilder.add(); + queueBuilder.update(data, this._renderGraph, this._lg, queueID, queue, this._pipeline); + return queueBuilder; } get showStatistics (): boolean { return this._subpass.showStatistics; @@ -1123,27 +1247,36 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB this._subpass.showStatistics = enable; } - private readonly _renderGraph: RenderGraph; - private readonly _vertID: number; - private readonly _layoutID: number; - private readonly _subpass: RasterSubpass; - private readonly _pipeline: PipelineSceneData; - private readonly _layoutGraph: LayoutGraphData; + private _renderGraph: RenderGraph; + private _vertID: number; + private _layoutID: number; + private _subpass: RasterSubpass; + private _pipeline: PipelineSceneData; } export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleRenderPassBuilder { constructor (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, resourceGraph: ResourceGraph, vertID: number, pass: RasterPass, pipeline: PipelineSceneData) { super(data, layoutGraph); this._renderGraph = renderGraph; - this._layoutGraph = layoutGraph; this._resourceGraph = resourceGraph; this._vertID = vertID; this._pass = pass; this._pipeline = pipeline; - const layoutName = this._renderGraph.component(RenderGraphComponent.Layout, this._vertID); this._layoutID = layoutGraph.locateChild(layoutGraph.nullVertex(), layoutName); } + update (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, resourceGraph: ResourceGraph, vertID: number, pass: RasterPass, pipeline: PipelineSceneData): void { + this._renderGraph = renderGraph; + this._lg = layoutGraph; + this._resourceGraph = resourceGraph; + this._vertID = vertID; + this._pass = pass; + this._pipeline = pipeline; + this._data = data; + const layoutName = this._renderGraph.component(RenderGraphComponent.Layout, this._vertID); + this._layoutID = layoutGraph.locateChild(layoutGraph.nullVertex(), layoutName); + } + setCustomShaderStages (name: string, stageFlags: ShaderStageFlagBit): void { throw new Error('Method not implemented.'); } @@ -1168,7 +1301,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR if (loadOp === LoadOp.LOAD) { clearFlag = ClearFlagBit.NONE; } - const view = new RasterView( + const view = renderGraphPool.createRasterView( '', AccessType.WRITE, @@ -1176,15 +1309,15 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR loadOp, storeOp, clearFlag, - clearColor, ); + view.clearColor.copy(clearColor); this._pass.rasterViews.set(name, view); } addDepthStencil (name: string, loadOp = LoadOp.CLEAR, storeOp = StoreOp.STORE, depth = 1, stencil = 0, clearFlag = ClearFlagBit.DEPTH_STENCIL): void { if (DEBUG) { assert(Boolean(name && this._resourceGraph.contains(name))); } - const view = new RasterView( + const view = renderGraphPool.createRasterView( '', AccessType.WRITE, @@ -1192,8 +1325,8 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR loadOp, storeOp, clearFlag, - new Color(depth, stencil, 0, 0), ); + view.clearColor.set(depth, stencil, 0, 0); this._pass.rasterViews.set(name, view); } resolveRenderTarget (source: string, target: string): void { @@ -1208,13 +1341,13 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR // TODO } private _addComputeResource (name: string, accessType: AccessType, slotName: string): void { - const view = new ComputeView(slotName); + const view = renderGraphPool.createComputeView(slotName); view.accessType = accessType; if (DEBUG) { assert(Boolean(view.name)); assert(Boolean(name && this._resourceGraph.contains(name))); const descriptorName = view.name; - const descriptorID = this._layoutGraph.attributeIndex.get(descriptorName); + const descriptorID = this._lg.attributeIndex.get(descriptorName); assert(descriptorID !== undefined); } if (this._pass.computeViews.has(name)) { @@ -1226,7 +1359,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR addTexture (name: string, slotName: string, sampler: Sampler | null = null): void { this._addComputeResource(name, AccessType.READ, slotName); if (sampler) { - const descriptorID = this._layoutGraph.attributeIndex.get(slotName)!; + const descriptorID = this._lg.attributeIndex.get(slotName)!; this._data.samplers.set(descriptorID, sampler); } } @@ -1239,64 +1372,66 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR addRenderSubpass (layoutName = ''): RenderSubpassBuilder { const name = 'Raster'; const subpassID = this._pass.subpassGraph.numVertices(); - this._pass.subpassGraph.addVertex(name, new Subpass()); - const subpass = new RasterSubpass(subpassID, 1, 0); - const data = new RenderData(); + this._pass.subpassGraph.addVertex(name, renderGraphPool.createSubpass()); + const subpass = renderGraphPool.createRasterSubpass(subpassID, 1, 0); + const data = renderGraphPool.createRenderData(); const vertID = this._renderGraph.addVertex(RenderGraphValue.RasterSubpass, subpass, name, layoutName, data, false); - const result = new WebRenderSubpassBuilder(data, this._renderGraph, this._layoutGraph, vertID, subpass, this._pipeline); + const result = pipelinePool.renderSubpassBuilder.add(); + result.update(data, this._renderGraph, this._lg, vertID, subpass, this._pipeline); return result; } addQueue (hint: QueueHint = QueueHint.RENDER_OPAQUE, layoutName = 'default'): WebRenderQueueBuilder { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); + const layoutId = this._lg.locateChild(this._layoutID, layoutName); if (DEBUG) { assert(layoutId !== 0xFFFFFFFF); } - const queue = new RenderQueue(hint); - queue.phaseID = layoutId; - const data = new RenderData(); + const queue = renderGraphPool.createRenderQueue(hint, layoutId); + const data = renderGraphPool.createRenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); - return new WebRenderQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); + const result = pipelinePool.renderQueueBuilder.add(); + result.update(data, this._renderGraph, this._lg, queueID, queue, this._pipeline); + return result; } addFullscreenQuad (material: Material, passID: number, sceneFlags = SceneFlags.NONE, name = 'FullscreenQuad'): void { - const queue = new RenderQueue(QueueHint.RENDER_TRANSPARENT); + const queue = renderGraphPool.createRenderQueue(QueueHint.RENDER_TRANSPARENT); const queueId = this._renderGraph.addVertex( RenderGraphValue.Queue, queue, 'Queue', '', - new RenderData(), + renderGraphPool.createRenderData(), false, this._vertID, ); this._renderGraph.addVertex( RenderGraphValue.Blit, - new Blit(material, passID, sceneFlags, null), + renderGraphPool.createBlit(material, passID, sceneFlags, null), name, '', - new RenderData(), + renderGraphPool.createRenderData(), false, queueId, ); } addCameraQuad (camera: Camera, material: Material, passID: number, sceneFlags: SceneFlags, name = 'CameraQuad'): void { - const queue = new RenderQueue(QueueHint.RENDER_TRANSPARENT); + const queue = renderGraphPool.createRenderQueue(QueueHint.RENDER_TRANSPARENT); const queueId = this._renderGraph.addVertex( RenderGraphValue.Queue, queue, 'Queue', '', - new RenderData(), + renderGraphPool.createRenderData(), false, this._vertID, ); this._renderGraph.addVertex( RenderGraphValue.Blit, - new Blit(material, passID, sceneFlags, camera), + renderGraphPool.createBlit(material, passID, sceneFlags, camera), name, '', - new RenderData(), + renderGraphPool.createRenderData(), false, queueId, ); @@ -1310,13 +1445,12 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR set showStatistics (enable: boolean) { this._pass.showStatistics = enable; } - private readonly _renderGraph: RenderGraph; - private readonly _vertID: number; - private readonly _layoutID: number; - private readonly _pass: RasterPass; - private readonly _pipeline: PipelineSceneData; - private readonly _layoutGraph: LayoutGraphData; - private readonly _resourceGraph: ResourceGraph; + private _renderGraph: RenderGraph; + private _vertID: number; + private _layoutID: number; + private _pass: RasterPass; + private _pipeline: PipelineSceneData; + private _resourceGraph: ResourceGraph; } export class WebComputeQueueBuilder extends WebSetter implements ComputeQueueBuilder { @@ -1327,6 +1461,14 @@ export class WebComputeQueueBuilder extends WebSetter implements ComputeQueueBui this._queue = queue; this._pipeline = pipeline; } + update (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, vertID: number, queue: RenderQueue, pipeline: PipelineSceneData): void { + this._data = data; + this._lg = layoutGraph; + this._renderGraph = renderGraph; + this._vertID = vertID; + this._queue = queue; + this._pipeline = pipeline; + } setArrayBuffer (name: string, arrayBuffer: ArrayBuffer): void { throw new Error('Method not implemented.'); } @@ -1346,29 +1488,40 @@ export class WebComputeQueueBuilder extends WebSetter implements ComputeQueueBui ): void { this._renderGraph.addVertex( RenderGraphValue.Dispatch, - new Dispatch(material, passID, threadGroupCountX, threadGroupCountY, threadGroupCountZ), + renderGraphPool.createDispatch(material, passID, threadGroupCountX, threadGroupCountY, threadGroupCountZ), name, '', - new RenderData(), + renderGraphPool.createRenderData(), false, this._vertID, ); } - private readonly _renderGraph: RenderGraph; - private readonly _vertID: number; - private readonly _queue: RenderQueue; - private readonly _pipeline: PipelineSceneData; + private _renderGraph: RenderGraph; + private _vertID: number; + private _queue: RenderQueue; + private _pipeline: PipelineSceneData; } export class WebComputePassBuilder extends WebSetter implements ComputePassBuilder { constructor (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, resourceGraph: ResourceGraph, vertID: number, pass: ComputePass, pipeline: PipelineSceneData) { super(data, layoutGraph); this._renderGraph = renderGraph; - this._layoutGraph = layoutGraph; + this._resourceGraph = resourceGraph; + this._vertID = vertID; + this._pass = pass; + this._pipeline = pipeline; + + const layoutName = this._renderGraph.component(RenderGraphComponent.Layout, this._vertID); + this._layoutID = layoutGraph.locateChild(layoutGraph.nullVertex(), layoutName); + } + update (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, resourceGraph: ResourceGraph, vertID: number, pass: ComputePass, pipeline: PipelineSceneData): void { + this._data = data; + this._renderGraph = renderGraph; + this._lg = layoutGraph; this._resourceGraph = resourceGraph; this._vertID = vertID; this._pass = pass; @@ -1402,25 +1555,26 @@ export class WebComputePassBuilder extends WebSetter implements ComputePassBuild throw new Error('Method not implemented.'); } addQueue (layoutName = 'default'): WebComputeQueueBuilder { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); + const layoutId = this._lg.locateChild(this._layoutID, layoutName); if (DEBUG) { assert(layoutId !== 0xFFFFFFFF); } - const queue = new RenderQueue(); - queue.phaseID = layoutId; - const data = new RenderData(); + const queue = renderGraphPool.createRenderQueue(QueueHint.RENDER_OPAQUE, layoutId); + const data = renderGraphPool.createRenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); - return new WebComputeQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); + const computeQueueBuilder = pipelinePool.computeQueueBuilder.add(); + computeQueueBuilder.update(data, this._renderGraph, this._lg, queueID, queue, this._pipeline); + return computeQueueBuilder; } private _addComputeResource (name: string, accessType: AccessType, slotName: string): void { - const view = new ComputeView(slotName); + const view = renderGraphPool.createComputeView(slotName); view.accessType = accessType; if (DEBUG) { assert(Boolean(view.name)); assert(Boolean(name && this._resourceGraph.contains(name))); const descriptorName = view.name; - const descriptorID = this._layoutGraph.attributeIndex.get(descriptorName); + const descriptorID = this._lg.attributeIndex.get(descriptorName); assert(descriptorID !== undefined); } if (this._pass.computeViews.has(name)) { @@ -1430,13 +1584,12 @@ export class WebComputePassBuilder extends WebSetter implements ComputePassBuild } } - private readonly _renderGraph: RenderGraph; - private readonly _layoutGraph: LayoutGraphData; - private readonly _resourceGraph: ResourceGraph; - private readonly _vertID: number; - private readonly _layoutID: number; - private readonly _pass: ComputePass; - private readonly _pipeline: PipelineSceneData; + private _renderGraph: RenderGraph; + private _resourceGraph: ResourceGraph; + private _vertID: number; + private _layoutID: number; + private _pass: ComputePass; + private _pipeline: PipelineSceneData; } export class WebMovePassBuilder { @@ -1507,6 +1660,7 @@ export class WebPipeline implements BasicPipeline { throw new Error('Method not implemented.'); } addRenderWindow (name: string, format: Format, width: number, height: number, renderWindow: RenderWindow): number { + // Objects need to be held for a long time, so there is no need to use pool management const desc = new ResourceDesc(); desc.dimension = ResourceDimension.TEXTURE2D; desc.width = width; @@ -1673,11 +1827,12 @@ export class WebPipeline implements BasicPipeline { public addComputePass (passName: string): ComputePassBuilder { const name = 'Compute'; - const pass = new ComputePass(); + const pass = renderGraphPool.createComputePass(); - const data = new RenderData(); + const data = renderGraphPool.createRenderData(); const vertID = this._renderGraph!.addVertex(RenderGraphValue.Compute, pass, name, passName, data, false); - const result = new WebComputePassBuilder(data, this._renderGraph!, this._layoutGraph, this._resourceGraph, vertID, pass, this._pipelineSceneData); + const result = pipelinePool.computePassBuilder.add(); + result.update(data, this._renderGraph!, this._layoutGraph, this._resourceGraph, vertID, pass, this._pipelineSceneData); setComputeConstants(result, passName); initGlobalDescBinding(data, passName); return result; @@ -1685,12 +1840,12 @@ export class WebPipeline implements BasicPipeline { public addUploadPass (uploadPairs: UploadPair[]): void { const name = 'UploadPass'; - const pass = new CopyPass(); + const pass = renderGraphPool.createCopyPass(); for (const up of uploadPairs) { pass.uploadPairs.push(up); } - const vertID = this._renderGraph!.addVertex(RenderGraphValue.Copy, pass, name, '', new RenderData(), false); + const vertID = this._renderGraph!.addVertex(RenderGraphValue.Copy, pass, name, '', renderGraphPool.createRenderData(), false); // const result = new WebCopyPassBuilder(this._renderGraph!, vertID, pass); } @@ -1713,7 +1868,7 @@ export class WebPipeline implements BasicPipeline { } const resDesc = this.resourceGraph.getDesc(tarVerId); const currRaster = this.addRenderPass(resDesc.width, resDesc.height, 'copy-pass'); - currRaster.addRenderTarget(targetName, LoadOp.CLEAR, StoreOp.STORE, new Color(0, 0, 0, 0)); + currRaster.addRenderTarget(targetName, LoadOp.CLEAR, StoreOp.STORE, pipelinePool.createColor()); currRaster.addTexture(pair.source, 'outputResultMap'); currRaster.addQueue(QueueHint.NONE).addFullscreenQuad(this._copyPassMat, 0, SceneFlags.NONE); } @@ -1780,6 +1935,8 @@ export class WebPipeline implements BasicPipeline { public activate (swapchain: Swapchain): boolean { this._device = deviceManager.gfxDevice; + pipelinePool = new PipelinePool(); + renderGraphPool = pipelinePool.renderGraphPool; createGfxDescriptorSetsAndPipelines(this._device, this._layoutGraph); this._globalDSManager = new GlobalDSManager(this._device); this._globalDescSetData = this.getGlobalDescriptorSetData()!; @@ -1937,6 +2094,7 @@ export class WebPipeline implements BasicPipeline { } beginSetup (): void { if (!this._renderGraph) this._renderGraph = new RenderGraph(); + pipelinePool.reset(); } endSetup (): void { this.compile(); @@ -2064,7 +2222,6 @@ export class WebPipeline implements BasicPipeline { // noop } endFrame (): void { - // this._renderGraph = null; this.renderGraph?.clear(); } @@ -2158,15 +2315,16 @@ export class WebPipeline implements BasicPipeline { assert(Boolean(layout.descriptorSets.get(UpdateFrequency.PER_PASS))); } const name = 'Raster'; - const pass = new RasterPass(); + const pass = renderGraphPool.createRasterPass(); pass.viewport.width = width; pass.viewport.height = height; pass.count = count; pass.quality = quality; - const data = new RenderData(); + const data = renderGraphPool.createRenderData(); const vertID = this._renderGraph!.addVertex(RenderGraphValue.RasterPass, pass, name, layoutName, data, false); - const result = new WebRenderPassBuilder(data, this._renderGraph!, this._layoutGraph, this._resourceGraph, vertID, pass, this._pipelineSceneData); + const result = pipelinePool.renderPassBuilder.add(); + result.update(data, this._renderGraph!, this._layoutGraph, this._resourceGraph, vertID, pass, this._pipelineSceneData); this._updateRasterPassConstants(result, width, height, layoutName); initGlobalDescBinding(data, layoutName); return result; From 6822e206cf6fd772ddccdfc2834e8d4981aa1957 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 21 Sep 2023 18:15:40 +0800 Subject: [PATCH 72/82] [Added] new pipeline setter's light interface (#175) * [Added] new pipeline setter's light interface * Update --------- Co-authored-by: hyde zhou --- cocos/rendering/custom/web-pipeline.ts | 213 +++++++++++++++--- .../renderer/pipeline/custom/NativeSetter.cpp | 88 ++++++++ 2 files changed, 274 insertions(+), 27 deletions(-) diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 528af286564..3ecbbc692a3 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -224,7 +224,7 @@ export class WebSetter implements Setter { const block: string = this._currBlock; const nodeId = this._lg.locateChild(0xFFFFFFFF, this._currStage); const ppl = this._lg.getLayout(nodeId); - const layout = ppl.descriptorSets.get(UpdateFrequency.PER_PASS)!.descriptorSetLayoutData; + const layout = ppl.descriptorSets.get(this._currFrequency)!.descriptorSetLayoutData; const nameID: number = this._lg.attributeIndex.get(block)!; return layout.uniformBlocks.get(nameID); } @@ -232,7 +232,7 @@ export class WebSetter implements Setter { protected _getCurrDescSetLayoutData (): DescriptorSetLayoutData { const nodeId = this._lg.locateChild(0xFFFFFFFF, this._currStage); const ppl = this._lg.getLayout(nodeId); - const layout = ppl.descriptorSets.get(UpdateFrequency.PER_PASS)!.descriptorSetLayoutData; + const layout = ppl.descriptorSets.get(this._currFrequency)!.descriptorSetLayoutData; return layout; } @@ -249,9 +249,10 @@ export class WebSetter implements Setter { return -1; } - setCurrConstant (block: string, stage = 'default'): boolean { + setCurrConstant (block: string, stage = 'default', frequency: UpdateFrequency = UpdateFrequency.PER_PASS): boolean { this._currBlock = block; this._currStage = stage; + this._currFrequency = frequency; const nameID: number = this._lg.attributeIndex.get(block)!; this._currCount = 0; const currBlock = this._getCurrUniformBlock(); @@ -267,9 +268,10 @@ export class WebSetter implements Setter { return this._currConstant; } - public addConstant (block: string, stage = 'default'): boolean { + public addConstant (block: string, stage = 'default', frequency: UpdateFrequency = UpdateFrequency.PER_PASS): boolean { this._currBlock = block; this._currStage = stage; + this._currFrequency = frequency; const num = this._lg.attributeIndex.get(block)!; this._currCount = 0; const currBlock = this._getCurrUniformBlock(); @@ -347,32 +349,195 @@ export class WebSetter implements Setter { const num = this._lg.attributeIndex.get(name)!; this._data.samplers.set(num, sampler); } + + public getParentLayout (): string { + const director = cclegacy.director; + const root = director.root; + const pipeline = root.pipeline as WebPipeline; + const parId = pipeline.renderGraph!.getParent(this._vertID); + const layoutName = pipeline.renderGraph!.getLayout(parId); + return layoutName; + } + + public getCurrentLayout (): string { + const director = cclegacy.director; + const root = director.root; + const pipeline = root.pipeline as WebPipeline; + const layoutName = pipeline.renderGraph!.getLayout(this._vertID); + return layoutName; + } + public setBuiltinCameraConstants (camera: Camera): void { - // TODO + const director = cclegacy.director; + const root = director.root; + const pipeline = root.pipeline as WebPipeline; + const layoutName = this.getParentLayout(); + setCameraUBOValues(this, camera, pipeline.pipelineSceneData, camera.scene, layoutName); } public setBuiltinShadowMapConstants (light: Light, numLevels?: number): void { - // TODO + setShadowUBOView(this, null, this.getParentLayout()); } public setBuiltinDirectionalLightFrustumConstants (camera: Camera, light: DirectionalLight, csmLevel = 0): void { setShadowUBOLightView(this, camera, light, csmLevel); } public setBuiltinSpotLightFrustumConstants (light: SpotLight): void { - // TODO + setShadowUBOLightView(this, null, light, 0); } public setBuiltinDirectionalLightConstants (light: DirectionalLight, camera: Camera): void { // TODO } public setBuiltinSphereLightConstants (light: SphereLight, camera: Camera): void { - // TODO + const director = cclegacy.director; + const pipeline = (director.root as Root).pipeline; + const sceneData = pipeline.pipelineSceneData; + if (!this.addConstant('CCForwardLight', this.getParentLayout(), UpdateFrequency.PER_BATCH)) return; + uniformOffset = this.getUniformOffset('cc_lightPos', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.position.x, light.position.y, light.position.z, LightType.SPHERE); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightSizeRangeAngle', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.size, light.range, 0.0, 0.0); + this.offsetVec4(_uboVec, uniformOffset); + } + const isHDR = sceneData.isHDR; + const lightMeterScale = 10000.0; + uniformOffset = this.getUniformOffset('cc_lightColor', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.color.x, light.color.y, light.color.z, 0); + if (light.useColorTemperature) { + const finalColor = light.finalColor; + _uboVec.x = finalColor.x; + _uboVec.y = finalColor.y; + _uboVec.z = finalColor.z; + } + if (isHDR) { + _uboVec.w = (light).luminance * camera.exposure * lightMeterScale; + } else { + _uboVec.w = (light).luminance; + } + this.offsetVec4(_uboVec, uniformOffset); + } } public setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void { - // TODO + const director = cclegacy.director; + const pipeline = (director.root as Root).pipeline; + const sceneData = pipeline.pipelineSceneData; + + const shadowInfo = sceneData.shadows; + if (!this.addConstant('CCForwardLight', this.getParentLayout(), UpdateFrequency.PER_BATCH)) return; + uniformOffset = this.getUniformOffset('cc_lightPos', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.position.x, light.position.y, light.position.z, LightType.SPOT); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightSizeRangeAngle', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.size, light.range, light.spotAngle, (shadowInfo.enabled && light.shadowEnabled && shadowInfo.type === ShadowType.ShadowMap) ? 1 : 0); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightDir', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.direction.x, light.direction.y, light.direction.z, 0); + this.offsetVec4(_uboVec, uniformOffset); + } + const isHDR = sceneData.isHDR; + const lightMeterScale = 10000.0; + uniformOffset = this.getUniformOffset('cc_lightColor', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.color.x, light.color.y, light.color.z, 0); + if (light.useColorTemperature) { + const finalColor = light.finalColor; + _uboVec.x = finalColor.x; + _uboVec.y = finalColor.y; + _uboVec.z = finalColor.z; + } + if (isHDR) { + _uboVec.w = (light).luminance * camera.exposure * lightMeterScale; + } else { + _uboVec.w = (light).luminance; + } + this.offsetVec4(_uboVec, uniformOffset); + } } public setBuiltinPointLightConstants (light: PointLight, camera: Camera): void { - // TODO + const director = cclegacy.director; + const pipeline = (director.root as Root).pipeline; + const sceneData = pipeline.pipelineSceneData; + if (!this.addConstant('CCForwardLight', this.getParentLayout(), UpdateFrequency.PER_BATCH)) return; + uniformOffset = this.getUniformOffset('cc_lightPos', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.position.x, light.position.y, light.position.z, LightType.POINT); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightSizeRangeAngle', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(0.0, light.range, 0.0, 0.0); + this.offsetVec4(_uboVec, uniformOffset); + } + const isHDR = sceneData.isHDR; + const lightMeterScale = 10000.0; + uniformOffset = this.getUniformOffset('cc_lightColor', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.color.x, light.color.y, light.color.z, 0); + if (light.useColorTemperature) { + const finalColor = light.finalColor; + _uboVec.x = finalColor.x; + _uboVec.y = finalColor.y; + _uboVec.z = finalColor.z; + } + if (isHDR) { + _uboVec.w = (light).luminance * camera.exposure * lightMeterScale; + } else { + _uboVec.w = (light).luminance; + } + this.offsetVec4(_uboVec, uniformOffset); + } } public setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void { - // TODO + const director = cclegacy.director; + const pipeline = (director.root as Root).pipeline; + const sceneData = pipeline.pipelineSceneData; + if (!this.addConstant('CCForwardLight', this.getParentLayout(), UpdateFrequency.PER_BATCH)) return; + uniformOffset = this.getUniformOffset('cc_lightPos', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.position.x, light.position.y, light.position.z, LightType.RANGED_DIRECTIONAL); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightSizeRangeAngle', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.right.x, light.right.y, light.right.z, 0.0); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightDir', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.direction.x, light.direction.y, light.direction.z, 0); + this.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = this.getUniformOffset('cc_lightBoundingSizeVS', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + const scale = light.scale; + _uboVec.set(scale.x * 0.5, scale.y * 0.5, scale.z * 0.5, 0); + this.offsetVec4(_uboVec, uniformOffset); + } + const isHDR = sceneData.isHDR; + uniformOffset = this.getUniformOffset('cc_lightColor', Type.FLOAT4); + if (this.hasUniform(uniformOffset)) { + _uboVec.set(light.color.x, light.color.y, light.color.z, 0); + if (light.useColorTemperature) { + const finalColor = light.finalColor; + _uboVec.x = finalColor.x; + _uboVec.y = finalColor.y; + _uboVec.z = finalColor.z; + } + if (isHDR) { + _uboVec.w = light.illuminance * camera.exposure; + } else { + _uboVec.w = light.illuminance; + } + this.offsetVec4(_uboVec, uniformOffset); + } } public hasSampler (name: string): boolean { const id = this._lg.attributeIndex.get(name); @@ -395,15 +560,17 @@ export class WebSetter implements Setter { // protected protected _data: RenderData; protected _lg: LayoutGraphData; + protected _vertID: number = -1; protected _currBlock; protected _currStage: string = ''; + protected _currFrequency: UpdateFrequency = UpdateFrequency.PER_PASS; protected _currCount; protected _currConstant: number[] = []; } function setShadowUBOLightView ( setter: WebSetter, - camera: Camera, + camera: Camera | null, light: Light, csmLevel: number, layout = 'default', @@ -426,8 +593,8 @@ function setShadowUBOLightView ( if (shadowInfo.enabled) { if (shadowInfo.type === ShadowType.ShadowMap) { // update CSM layers - if (light && light.node) { - csmLayers.update(sceneData, camera); + if (light && light.node && light.type === LightType.DIRECTIONAL) { + csmLayers.update(sceneData, camera!); } } } @@ -997,7 +1164,7 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder { const queueId = this._renderGraph.getParent(this._sceneId); const passId = this._renderGraph.getParent(queueId); const layoutName = this._renderGraph.getLayout(passId); - setShadowUBOLightView(this, this._scene.camera!, light, csmLevel, layoutName); + setShadowUBOLightView(this, this._scene.camera, light, csmLevel, layoutName); } private _renderGraph: RenderGraph; private _scene: SceneData; @@ -1031,16 +1198,10 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild this._renderGraph.setName(this._vertID, name); } - getLayoutName (): string { - const parId = this._renderGraph.getParent(this._vertID); - const layoutName = this._renderGraph.getLayout(parId); - return layoutName; - } - addSceneOfCamera (camera: Camera, light: LightInfo, sceneFlags = SceneFlags.NONE, name = 'Camera'): void { const sceneData = renderGraphPool.createSceneData(camera.scene, camera, sceneFlags, CullingFlags.NONE, light.light); this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, name, '', renderGraphPool.createRenderData(), false, this._vertID); - const layoutName = this.getLayoutName(); + const layoutName = this.getParentLayout(); const scene: Scene = cclegacy.director.getScene(); setCameraUBOValues( this, @@ -1065,7 +1226,7 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild const renderData = renderGraphPool.createRenderData(); const sceneId = this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); if (!(sceneFlags & SceneFlags.NON_BUILTIN)) { - const layoutName = this.getLayoutName(); + const layoutName = this.getParentLayout(); setCameraUBOValues( this, camera, @@ -1091,7 +1252,7 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild false, this._vertID, ); - const layoutName = this.getLayoutName(); + const layoutName = this.getParentLayout(); const scene: Scene | null = cclegacy.director.getScene(); setCameraUBOValues( this, @@ -1118,7 +1279,7 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild false, this._vertID, ); - const layoutName = this.getLayoutName(); + const layoutName = this.getParentLayout(); const scene: Scene = cclegacy.director.getScene(); setCameraUBOValues( this, @@ -1156,7 +1317,6 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild throw new Error('Method not implemented.'); } private _renderGraph: RenderGraph; - private _vertID: number; private _queue: RenderQueue; private _pipeline: PipelineSceneData; } @@ -1246,7 +1406,6 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB set showStatistics (enable: boolean) { this._subpass.showStatistics = enable; } - private _renderGraph: RenderGraph; private _vertID: number; private _layoutID: number; diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index e78cf4fb073..958cc5b5b7c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -165,6 +165,35 @@ void NativeSetter::setBuiltinDirectionalLightConstants(const scene::DirectionalL } void NativeSetter::setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) { + const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); + const auto &shadowInfo = *sceneData.getShadows(); + + auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::SPHERE))); + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; + } else { + color.w = light->getLuminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + light->getSize(), + light->getRange(), + 0.F, + 0.F)); } void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) { @@ -212,9 +241,68 @@ void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, c } void NativeSetter::setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) { + const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); + const auto &shadowInfo = *sceneData.getShadows(); + + auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::POINT))); + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; + } else { + color.w = light->getLuminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + 0.F, + light->getRange(), + 0.F, + 0.F)); } void NativeSetter::setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) { + const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); + const auto &shadowInfo = *sceneData.getShadows(); + + auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::RANGED_DIRECTIONAL))); + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getIlluminance() * camera->getExposure(); + } else { + color.w = light->getIlluminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + light->getRight().x, + light->getRight().y, + light->getRight().z, + 0.F)); + } } // namespace render From 760f2a6b7dc1e23108bacaf73319de07d55c442e Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 22 Sep 2023 16:37:20 +0800 Subject: [PATCH 73/82] [Fixed] sampler synchronization issues with compute view texture (#178) --- cocos/rendering/custom/executor.ts | 108 ++++++++++--------------- cocos/rendering/custom/web-pipeline.ts | 11 +-- 2 files changed, 47 insertions(+), 72 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index e2567007219..c2b3bd61379 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -28,7 +28,7 @@ * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= */ /* eslint-disable max-len */ -import { getPhaseID, InstancedBuffer, PipelineStateManager } from '..'; +import { getPhaseID, PipelineStateManager } from '..'; import { assert, cclegacy, RecyclePool } from '../../core'; import intersect from '../../core/geometry/intersect'; import { Sphere } from '../../core/geometry/sphere'; @@ -36,7 +36,6 @@ import { AccessFlagBit, Attribute, Buffer, - BufferFlagBit, BufferInfo, BufferUsageBit, BufferViewInfo, @@ -75,7 +74,6 @@ import { import { legacyCC } from '../../core/global-exports'; import { Vec3 } from '../../core/math/vec3'; import { Vec4 } from '../../core/math/vec4'; -import { IMacroPatch, Pass } from '../../render-scene'; import { Camera } from '../../render-scene/scene/camera'; import { ShadowType } from '../../render-scene/scene/shadows'; import { Root } from '../../root'; @@ -144,7 +142,7 @@ import { } from './define'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; import { SceneCulling } from './scene-culling'; -import { WebPipeline } from './web-pipeline'; +import { Pass } from '../../render-scene'; class ResourceVisitor implements ResourceGraphVisitor { name: string; @@ -508,7 +506,6 @@ class BlitDesc { const deferredLitsBufView = context.blit.deferredLitsBufView; this._lightBufferData = context.blit.lightBufferData; this._lightBufferData.fill(0); - // const binding = isEnableEffect() ? getDescBindingFromName('CCForwardLight') : UBOForwardLight.BINDING; this._stageDesc.bindBuffer(UBOForwardLight.BINDING, deferredLitsBufView); } this._stageDesc.bindBuffer(UBOLocal.BINDING, context.blit.emptyLocalUBO); @@ -700,62 +697,58 @@ class SubmitInfo { class RenderPassLayoutInfo { protected _layoutID = 0; + protected _vertID = -1; protected _stage: RenderStageData | null = null; protected _layout: PipelineLayoutData; protected _inputName: string; protected _descriptorSet: DescriptorSet | null = null; - constructor (layoutId: number, input: [string, ComputeView[]]) { + constructor (layoutId: number, vertId: number, input: [string, ComputeView[]]) { this._inputName = input[0]; this._layoutID = layoutId; + this._vertID = vertId; const lg = context.layoutGraph; this._stage = lg.getRenderStage(layoutId); this._layout = lg.getLayout(layoutId); const layoutData = this._layout.descriptorSets.get(UpdateFrequency.PER_PASS); - // const globalDesc = context.descriptorSet; - if (layoutData) { - const layoutDesc = layoutData.descriptorSet!; - // find resource - const deviceTex = context.deviceTextures.get(this._inputName); - const gfxTex = deviceTex?.texture; - - const deviceBuf = context.deviceBuffers.get(this._inputName); - const gfxBuf = deviceBuf?.buffer; - if (!gfxTex && !gfxBuf) { - throw Error(`Could not find texture with resource name ${this._inputName}`); - } - const resId = context.resourceGraph.vertex(this._inputName); - const samplerInfo = context.resourceGraph.getSampler(resId); - // bind descriptors - for (const descriptor of input[1]) { - const descriptorName = descriptor.name; - const descriptorID = lg.attributeIndex.get(descriptorName); - // find descriptor binding - for (const block of layoutData.descriptorSetLayoutData.descriptorBlocks) { - for (let i = 0; i !== block.descriptors.length; ++i) { - // const buffer = layoutDesc.getBuffer(block.offset + i); - // const texture = layoutDesc.getTexture(block.offset + i); - if (descriptorID === block.descriptors[i].descriptorID) { - if (gfxTex) { - layoutDesc.bindTexture(block.offset + i, gfxTex); - layoutDesc.bindSampler(block.offset + i, context.device.getSampler(samplerInfo)); + if (!layoutData) { + return; + } + const layoutDesc = layoutData.descriptorSet!; + // find resource + const deviceTex = context.deviceTextures.get(this._inputName); + const gfxTex = deviceTex?.texture; + + const deviceBuf = context.deviceBuffers.get(this._inputName); + const gfxBuf = deviceBuf?.buffer; + if (!gfxTex && !gfxBuf) { + throw Error(`Could not find texture with resource name ${this._inputName}`); + } + const resId = context.resourceGraph.vertex(this._inputName); + const samplerInfo = context.resourceGraph.getSampler(resId); + // bind descriptors + for (const descriptor of input[1]) { + const descriptorName = descriptor.name; + const descriptorID = lg.attributeIndex.get(descriptorName); + // find descriptor binding + for (const block of layoutData.descriptorSetLayoutData.descriptorBlocks) { + for (let i = 0; i !== block.descriptors.length; ++i) { + if (descriptorID === block.descriptors[i].descriptorID) { + if (gfxTex) { + layoutDesc.bindTexture(block.offset + i, gfxTex); + const renderData = context.renderGraph.getData(this._vertID); + layoutDesc.bindSampler(block.offset + i, renderData.samplers.get(descriptorID) || context.device.getSampler(samplerInfo)); + } else { + const desc = context.resourceGraph.getDesc(resId); + if (desc.flags & ResourceFlags.STORAGE) { + const access = input[1][0].accessType !== AccessType.READ ? AccessFlagBit.COMPUTE_SHADER_WRITE + : AccessFlagBit.COMPUTE_SHADER_READ_OTHER; + (layoutDesc as any).bindBuffer(block.offset + i, gfxBuf!, 0, access); } else { - const desc = context.resourceGraph.getDesc(resId); - if (desc.flags & ResourceFlags.STORAGE) { - const access = input[1][0].accessType !== AccessType.READ ? AccessFlagBit.COMPUTE_SHADER_WRITE - : AccessFlagBit.COMPUTE_SHADER_READ_OTHER; - (layoutDesc as any).bindBuffer(block.offset + i, gfxBuf!, 0, access); - } else { - layoutDesc.bindBuffer(block.offset + i, gfxBuf!); - } + layoutDesc.bindBuffer(block.offset + i, gfxBuf!); } - if (!this._descriptorSet) this._descriptorSet = layoutDesc; - continue; } - // if (!buffer && !texture) { - // layoutDesc.bindBuffer(block.offset + i, globalDesc.getBuffer(block.offset + i)); - // layoutDesc.bindTexture(block.offset + i, globalDesc.getTexture(block.offset + i)); - // layoutDesc.bindSampler(block.offset + i, globalDesc.getSampler(block.offset + i)); - // } + if (!this._descriptorSet) this._descriptorSet = layoutDesc; + continue; } } } @@ -763,6 +756,7 @@ class RenderPassLayoutInfo { } get descriptorSet (): DescriptorSet | null { return this._descriptorSet; } get layoutID (): number { return this._layoutID; } + get vertID (): number { return this._vertID; } get stage (): RenderStageData | null { return this._stage; } get layout (): PipelineLayoutData { return this._layout; } } @@ -927,15 +921,6 @@ class DeviceRenderPass { const currTex = device.createTexture(new TextureInfo()); colorTexs.push(currTex); } - // if (!depthTex && !swapchain && !framebuffer) { - // depthTex = device.createTexture(new TextureInfo( - // TextureType.TEX2D, - // TextureUsageBit.DEPTH_STENCIL_ATTACHMENT | TextureUsageBit.SAMPLED, - // Format.DEPTH_STENCIL, - // colorTexs[0].width, - // colorTexs[0].height, - // )); - // } const depth = swapchain ? swapchain.depthStencilTexture : depthTex; if (!depth) { depthStencilAttachment.format = Format.UNKNOWN; @@ -977,7 +962,7 @@ class DeviceRenderPass { const layoutGraph = context.layoutGraph; const stageId = layoutGraph.locateChild(layoutGraph.nullVertex(), stageName); if (stageId !== 0xFFFFFFFF) { - this._layout = new RenderPassLayoutInfo(stageId, input); + this._layout = new RenderPassLayoutInfo(stageId, this.rasterPassInfo.id, input); } } } @@ -1068,7 +1053,6 @@ class DeviceRenderPass { } postPass (): void { - // this.submitMap.clear(); for (const queue of this._deviceQueues) { queue.postRecord(); } @@ -1231,7 +1215,7 @@ class DeviceComputePass { const layoutGraph = context.layoutGraph; const stageId = layoutGraph.locateChild(layoutGraph.nullVertex(), stageName); if (stageId !== 0xFFFFFFFF) { - this._layout = new RenderPassLayoutInfo(stageId, input); + this._layout = new RenderPassLayoutInfo(stageId, this._computeInfo.id, input); } } } @@ -1405,10 +1389,6 @@ class DevicePreSceneTask extends WebSceneTask { if (this.graphScene.blit) { this._currentQueue.blitDesc!.update(); } - // if (isShadowMap(this.graphScene)) { - - // } - // this._uploadInstanceBuffers(); } } const sceneViewport = new Viewport(); diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 3ecbbc692a3..9c26269b844 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -1135,7 +1135,7 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder { super(data, layoutGraph); this._renderGraph = rg; this._scene = scene; - this._sceneId = sceneId; + this._vertID = sceneId; } update ( data: RenderData, @@ -1148,7 +1148,7 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder { this._lg = layoutGraph; this._renderGraph = rg; this._scene = scene; - this._sceneId = sceneId; + this._vertID = sceneId; } useLightFrustum (light: Light, csmLevel = 0, optCamera: Camera | undefined = undefined): void { @@ -1161,14 +1161,13 @@ export class WebSceneBuilder extends WebSetter implements SceneBuilder { if (this._scene.flags & SceneFlags.NON_BUILTIN) { return; } - const queueId = this._renderGraph.getParent(this._sceneId); + const queueId = this._renderGraph.getParent(this._vertID); const passId = this._renderGraph.getParent(queueId); const layoutName = this._renderGraph.getLayout(passId); setShadowUBOLightView(this, this._scene.camera, light, csmLevel, layoutName); } private _renderGraph: RenderGraph; private _scene: SceneData; - private _sceneId: number; } export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuilder { @@ -1407,7 +1406,6 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB this._subpass.showStatistics = enable; } private _renderGraph: RenderGraph; - private _vertID: number; private _layoutID: number; private _subpass: RasterSubpass; private _pipeline: PipelineSceneData; @@ -1605,7 +1603,6 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR this._pass.showStatistics = enable; } private _renderGraph: RenderGraph; - private _vertID: number; private _layoutID: number; private _pass: RasterPass; private _pipeline: PipelineSceneData; @@ -1660,7 +1657,6 @@ export class WebComputeQueueBuilder extends WebSetter implements ComputeQueueBui ); } private _renderGraph: RenderGraph; - private _vertID: number; private _queue: RenderQueue; private _pipeline: PipelineSceneData; } @@ -1745,7 +1741,6 @@ export class WebComputePassBuilder extends WebSetter implements ComputePassBuild private _renderGraph: RenderGraph; private _resourceGraph: ResourceGraph; - private _vertID: number; private _layoutID: number; private _pass: ComputePass; private _pipeline: PipelineSceneData; From 6f18470fcccd2f813abdb5b95f663173962c1623 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 22 Sep 2023 17:08:19 +0800 Subject: [PATCH 74/82] punctual light ubo added --- .../pipeline/custom/NativeBuiltinUtils.cpp | 124 ++++++++- .../pipeline/custom/NativeBuiltinUtils.h | 8 + .../pipeline/custom/NativeRenderGraph.cpp | 27 +- .../renderer/pipeline/custom/NativeSetter.cpp | 241 ++++++++++-------- 4 files changed, 278 insertions(+), 122 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp index 9f408052350..325d2ad31fc 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.cpp @@ -258,12 +258,12 @@ float getPCFRadius( void setShadowUBOView( gfx::Device &device, const LayoutGraphData &layoutGraph, - const pipeline::PipelineSceneData &sceneData, + const pipeline::PipelineSceneData &pplSceneData, const scene::DirectionalLight &mainLight, RenderData &data) { - const auto &shadowInfo = *sceneData.getShadows(); - const auto &csmLayers = *sceneData.getCSMLayers(); - const auto &csmSupported = sceneData.getCSMSupported(); + const auto &shadowInfo = *pplSceneData.getShadows(); + const auto &csmLayers = *pplSceneData.getCSMLayers(); + const auto &csmSupported = pplSceneData.getCSMSupported(); const auto &packing = pipeline::supportsR32FloatTexture(&device) ? 0.0F : 1.0F; Vec4 vec4ShadowInfo{}; if (shadowInfo.isEnabled()) { @@ -373,12 +373,12 @@ void setShadowUBOView( void setShadowUBOLightView( gfx::Device *device, const LayoutGraphData &layoutGraph, - const pipeline::PipelineSceneData &sceneData, + const pipeline::PipelineSceneData &pplSceneData, const BuiltinCascadedShadowMap *csm, const scene::Light &light, uint32_t level, RenderData &data) { - const auto &shadowInfo = *sceneData.getShadows(); + const auto &shadowInfo = *pplSceneData.getShadows(); const auto &packing = pipeline::supportsR32FloatTexture(device) ? 0.0F : 1.0F; const auto &cap = device->getCapabilities(); Vec4 vec4ShadowInfo{}; @@ -491,12 +491,120 @@ void setShadowUBOLightView( setColorImpl(data, layoutGraph, "cc_shadowColor", gfx::Color{color[0], color[1], color[2], color[3]}); } +namespace { + +void updatePlanarNormalAndDistance( + const LayoutGraphData &layoutGraph, + const scene::Shadows &shadowInfo, + RenderData &data) { + const Vec3 normal = shadowInfo.getNormal().getNormalized(); + const Vec4 planarNDInfo{normal.x, normal.y, normal.z, -shadowInfo.getDistance()}; + setVec4Impl(data, layoutGraph, "cc_planarNDInfo", planarNDInfo); +} + +std::tuple +computeShadowMatrices( + const gfx::DeviceCaps &cap, + const Mat4 &matShadowCamera, + float fov, float farPlane) { + auto matShadowView = matShadowCamera.getInversed(); + + Mat4 matShadowProj; + Mat4::createPerspective( + fov, 1.0F, 0.001F, farPlane, + true, cap.clipSpaceMinZ, cap.clipSpaceSignY, + 0, &matShadowProj); + + Mat4 matShadowViewProj = matShadowProj; + Mat4 matShadowInvProj = matShadowProj; + + matShadowInvProj.inverse(); + matShadowViewProj.multiply(matShadowView); + + return {matShadowView, matShadowViewProj, matShadowProj, matShadowInvProj}; +} + +} // namespace + +void setPunctualLightShadowUBO( + gfx::Device *device, + const LayoutGraphData &layoutGraph, + const pipeline::PipelineSceneData &pplSceneData, + const scene::DirectionalLight *mainLight, + const scene::Light &light, + RenderData &data) { + const auto &shadowInfo = *pplSceneData.getShadows(); + const auto &packing = pipeline::supportsR32FloatTexture(device) ? 0.0F : 1.0F; + const auto &cap = device->getCapabilities(); + Vec4 vec4ShadowInfo{}; + + if (mainLight) { + // update planar PROJ + updatePlanarNormalAndDistance(layoutGraph, shadowInfo, data); + } + + // ShadowMap + switch (light.getType()) { + case scene::LightType::DIRECTIONAL: + // noop + break; + case scene::LightType::SPHERE: { + const auto &shadowSize = shadowInfo.getSize(); + setVec4Impl( + data, layoutGraph, "cc_shadowWHPBInfo", + Vec4{shadowSize.x, shadowSize.y, 1.0F, 0.0F}); + setVec4Impl( + data, layoutGraph, "cc_shadowLPNNInfo", + Vec4{static_cast(scene::LightType::SPHERE), packing, 0.0F, 0.0F}); + } break; + case scene::LightType::SPOT: { + const auto &shadowSize = shadowInfo.getSize(); + const auto &spotLight = dynamic_cast(light); + const auto &matShadowCamera = spotLight.getNode()->getWorldMatrix(); + const auto [matShadowView, matShadowViewProj, matShadowProj, matShadowInvProj] = + computeShadowMatrices(cap, matShadowCamera, spotLight.getAngle(), spotLight.getRange()); + + setMat4Impl(data, layoutGraph, "cc_matLightView", matShadowView); + setMat4Impl(data, layoutGraph, "cc_matLightViewProj", matShadowViewProj); + setVec4Impl( + data, layoutGraph, "cc_shadowNFLSInfo", + Vec4{0.1F, spotLight.getRange(), 0.0F, 0.0F}); + setVec4Impl( + data, layoutGraph, "cc_shadowWHPBInfo", + Vec4{shadowSize.x, shadowSize.y, spotLight.getShadowPcf(), spotLight.getShadowBias()}); + setVec4Impl( + data, layoutGraph, "cc_shadowLPNNInfo", + Vec4{static_cast(scene::LightType::SPOT), packing, spotLight.getShadowNormalBias(), 0.0F}); + setVec4Impl( + data, layoutGraph, "cc_shadowInvProjDepthInfo", + Vec4{matShadowInvProj.m[10], matShadowInvProj.m[14], matShadowInvProj.m[11], matShadowInvProj.m[15]}); + setVec4Impl( + data, layoutGraph, "cc_shadowProjDepthInfo", + Vec4{matShadowProj.m[10], matShadowProj.m[14], matShadowProj.m[11], matShadowProj.m[15]}); + setVec4Impl( + data, layoutGraph, "cc_shadowProjInfo", + Vec4{matShadowProj.m[00], matShadowProj.m[05], 1.0F / matShadowProj.m[00], 1.0F / matShadowProj.m[05]}); + } break; + case scene::LightType::POINT: { + const auto &shadowSize = shadowInfo.getSize(); + setVec4Impl( + data, layoutGraph, "cc_shadowWHPBInfo", + Vec4{shadowSize.x, shadowSize.y, 1.0F, 0.0F}); + setVec4Impl( + data, layoutGraph, "cc_shadowLPNNInfo", + Vec4{static_cast(scene::LightType::POINT), packing, 0.0F, 0.0F}); + } break; + default: + break; + } +} + void setLegacyTextureUBOView( gfx::Device &device, const LayoutGraphData &layoutGraph, - const pipeline::PipelineSceneData &sceneData, + const pipeline::PipelineSceneData &pplSceneData, RenderData &data) { - const auto &skybox = *sceneData.getSkybox(); + const auto &skybox = *pplSceneData.getSkybox(); if (skybox.getReflectionMap()) { auto &texture = *skybox.getReflectionMap()->getGFXTexture(); auto *sampler = device.getSampler(skybox.getReflectionMap()->getSamplerInfo()); diff --git a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h index 9d5ad1814e1..9c74502dfaa 100644 --- a/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeBuiltinUtils.h @@ -91,6 +91,14 @@ void setLightUBO( const scene::Shadows *shadowInfo, char *buffer, size_t bufferSize); +void setPunctualLightShadowUBO( + gfx::Device *device, + const LayoutGraphData &layoutGraph, + const pipeline::PipelineSceneData &pplSceneData, + const scene::DirectionalLight *mainLight, + const scene::Light &light, + RenderData &data); + // Render graph void updateRasterPassConstants(uint32_t width, uint32_t height, Setter &setter); diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 304f76fbf5d..2f39f625e75 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -818,11 +818,28 @@ SceneBuilder *NativeRenderQueueBuilder::addScene( // objects are projected to camera, set camera ubo builder->setBuiltinCameraConstants(camera); - if (const auto *pDirLight = dynamic_cast(light); pDirLight) { - // light is directional - builder->setBuiltinDirectionalLightConstants(pDirLight, camera); - } else if (light) { // light is non-directional - // TODO(zhouzhenglong): refactor per-instance lighting + if (light) { + switch (light->getType()) { + case scene::LightType::DIRECTIONAL: { + const auto *pDirLight = dynamic_cast(light); + builder->setBuiltinDirectionalLightConstants(pDirLight, camera); + } break; + case scene::LightType::SPHERE: { + const auto *pSphereLight = dynamic_cast(light); + builder->setBuiltinSphereLightConstants(pSphereLight, camera); + } break; + case scene::LightType::SPOT: { + const auto *pSpotLight = dynamic_cast(light); + builder->setBuiltinSpotLightConstants(pSpotLight, camera); + } break; + case scene::LightType::POINT: { + const auto *pPointLight = dynamic_cast(light); + builder->setBuiltinPointLightConstants(pPointLight, camera); + } break; + default: + // noop + break; + } } // set builtin legacy ubo diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index 958cc5b5b7c..16141922bd0 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -158,42 +158,51 @@ void NativeSetter::setBuiltinShadowMapConstants( namespace { constexpr float LIGHT_METER_SCALE = 10000.0F; +constexpr bool ENABLE_NEW_MULTI_LIGHT = false; } // namespace void NativeSetter::setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) { } -void NativeSetter::setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) { - const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); +void NativeSetter::setBuiltinSphereLightConstants( + const scene::SphereLight *light, const scene::Camera *camera) { + CC_EXPECTS(light); + const auto &sceneData = *pipelineRuntime->getPipelineSceneData(); const auto &shadowInfo = *sceneData.getShadows(); auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); - setVec4Impl( - data, *layoutGraph, "cc_lightPos", - toVec4(light->getPosition(), static_cast(scene::LightType::SPHERE))); - auto color = toVec4(light->getColor()); - if (light->isUseColorTemperature()) { - const auto &rgb = light->getColorTemperatureRGB(); - color.x *= rgb.x; - color.y *= rgb.y; - color.z *= rgb.z; - } - if (sceneData.isHDR()) { - color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; - } else { - color.w = light->getLuminance(); - } - setVec4Impl( - data, *layoutGraph, "cc_lightColor", color); - setVec4Impl( - data, *layoutGraph, "cc_lightSizeRangeAngle", - Vec4( - light->getSize(), - light->getRange(), - 0.F, - 0.F)); + if constexpr (ENABLE_NEW_MULTI_LIGHT) { + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::SPHERE))); + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; + } else { + color.w = light->getLuminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + light->getSize(), + light->getRange(), + 0.F, + 0.F)); + } + setPunctualLightShadowUBO( + pipelineRuntime->getDevice(), *layoutGraph, sceneData, + camera->getScene()->getMainLight(), *light, data); } void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) { @@ -203,73 +212,85 @@ void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, c auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); - setVec4Impl( - data, *layoutGraph, "cc_lightPos", - toVec4(light->getPosition(), static_cast(scene::LightType::SPOT))); - - auto color = toVec4(light->getColor()); - if (light->isUseColorTemperature()) { - const auto &rgb = light->getColorTemperatureRGB(); - color.x *= rgb.x; - color.y *= rgb.y; - color.z *= rgb.z; + if constexpr (ENABLE_NEW_MULTI_LIGHT) { + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::SPOT))); + + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; + } else { + color.w = light->getLuminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + light->getSize(), + light->getRange(), + light->getSpotAngle(), + shadowInfo.isEnabled() && + light->isShadowEnabled() && + shadowInfo.getType() == scene::ShadowType::SHADOW_MAP + ? 1.0F + : 0.0F)); + + setVec4Impl( + data, *layoutGraph, "cc_lightDir", + toVec4(light->getDirection())); } - if (sceneData.isHDR()) { - color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; - } else { - color.w = light->getLuminance(); - } - - setVec4Impl( - data, *layoutGraph, "cc_lightColor", color); - - setVec4Impl( - data, *layoutGraph, "cc_lightSizeRangeAngle", - Vec4( - light->getSize(), - light->getRange(), - light->getSpotAngle(), - shadowInfo.isEnabled() && - light->isShadowEnabled() && - shadowInfo.getType() == scene::ShadowType::SHADOW_MAP - ? 1.0F - : 0.0F)); - - setVec4Impl( - data, *layoutGraph, "cc_lightDir", - toVec4(light->getDirection())); + setPunctualLightShadowUBO( + pipelineRuntime->getDevice(), *layoutGraph, sceneData, + camera->getScene()->getMainLight(), *light, data); } void NativeSetter::setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) { + CC_EXPECTS(light); const auto &sceneData = *this->pipelineRuntime->getPipelineSceneData(); const auto &shadowInfo = *sceneData.getShadows(); auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); - setVec4Impl( - data, *layoutGraph, "cc_lightPos", - toVec4(light->getPosition(), static_cast(scene::LightType::POINT))); - auto color = toVec4(light->getColor()); - if (light->isUseColorTemperature()) { - const auto &rgb = light->getColorTemperatureRGB(); - color.x *= rgb.x; - color.y *= rgb.y; - color.z *= rgb.z; - } - if (sceneData.isHDR()) { - color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; - } else { - color.w = light->getLuminance(); - } - setVec4Impl( - data, *layoutGraph, "cc_lightColor", color); - setVec4Impl( - data, *layoutGraph, "cc_lightSizeRangeAngle", - Vec4( - 0.F, - light->getRange(), - 0.F, - 0.F)); + if constexpr (ENABLE_NEW_MULTI_LIGHT) { + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::POINT))); + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getLuminance() * camera->getExposure() * LIGHT_METER_SCALE; + } else { + color.w = light->getLuminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + 0.F, + light->getRange(), + 0.F, + 0.F)); + } + setPunctualLightShadowUBO( + pipelineRuntime->getDevice(), *layoutGraph, sceneData, + camera->getScene()->getMainLight(), *light, data); } void NativeSetter::setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) { @@ -277,32 +298,34 @@ void NativeSetter::setBuiltinRangedDirectionalLightConstants(const scene::Ranged const auto &shadowInfo = *sceneData.getShadows(); auto &data = get(RenderGraph::DataTag{}, *renderGraph, nodeID); - setVec4Impl( - data, *layoutGraph, "cc_lightPos", - toVec4(light->getPosition(), static_cast(scene::LightType::RANGED_DIRECTIONAL))); - auto color = toVec4(light->getColor()); - if (light->isUseColorTemperature()) { - const auto &rgb = light->getColorTemperatureRGB(); - color.x *= rgb.x; - color.y *= rgb.y; - color.z *= rgb.z; - } - if (sceneData.isHDR()) { - color.w = light->getIlluminance() * camera->getExposure(); - } else { - color.w = light->getIlluminance(); - } - - setVec4Impl( - data, *layoutGraph, "cc_lightColor", color); - setVec4Impl( - data, *layoutGraph, "cc_lightSizeRangeAngle", - Vec4( - light->getRight().x, - light->getRight().y, - light->getRight().z, - 0.F)); + if constexpr (ENABLE_NEW_MULTI_LIGHT) { + setVec4Impl( + data, *layoutGraph, "cc_lightPos", + toVec4(light->getPosition(), static_cast(scene::LightType::RANGED_DIRECTIONAL))); + auto color = toVec4(light->getColor()); + if (light->isUseColorTemperature()) { + const auto &rgb = light->getColorTemperatureRGB(); + color.x *= rgb.x; + color.y *= rgb.y; + color.z *= rgb.z; + } + if (sceneData.isHDR()) { + color.w = light->getIlluminance() * camera->getExposure(); + } else { + color.w = light->getIlluminance(); + } + + setVec4Impl( + data, *layoutGraph, "cc_lightColor", color); + setVec4Impl( + data, *layoutGraph, "cc_lightSizeRangeAngle", + Vec4( + light->getRight().x, + light->getRight().y, + light->getRight().z, + 0.F)); + } } } // namespace render From 6fdba8ab0c387d76beef49a34d81c2cb48f41832 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Fri, 22 Sep 2023 18:03:52 +0800 Subject: [PATCH 75/82] spot light shadow map added --- .../pipeline/custom/NativeRenderGraph.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 2f39f625e75..a11df267403 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -779,11 +779,18 @@ void NativeSceneBuilder::useLightFrustum( return; } - const auto *pLight = dynamic_cast(light.get()); - if (pLight) { - setBuiltinDirectionalLightFrustumConstants(sceneData.camera, pLight, csmLevel); - } else { - CC_EXPECTS(false); + switch (light->getType()) { + case scene::LightType::DIRECTIONAL: { + setBuiltinDirectionalLightFrustumConstants( + sceneData.camera, dynamic_cast(light.get()), csmLevel); + } break; + case scene::LightType::SPOT: { + setBuiltinSpotLightFrustumConstants( + dynamic_cast(light.get())); + } break; + default: + // noop + break; } } From 57f2f8d0bcd83e82090c3c97b755755450b117d8 Mon Sep 17 00:00:00 2001 From: Zhou Zhenglong Date: Tue, 10 Oct 2023 18:14:29 +0800 Subject: [PATCH 76/82] add guard to buildLightBuffer --- native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index 36e43830185..2b6cf72cf8c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -775,6 +775,9 @@ void LightResource::clear() { } void LightResource::buildLightBuffer(gfx::CommandBuffer* cmdBuffer) const { + if (lights.empty()) { + return; + } cmdBuffer->updateBuffer( lightBuffer, cpuBuffer.data(), From 9dca300457206027778115f53ed88cc914b621e7 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 13 Oct 2023 11:23:48 +0800 Subject: [PATCH 77/82] [Complete] multi-light source adjustment logic (#179) * Complete multi-light source adjustment logic * Spotlight logic adjustment correct effect --- cocos/asset/assets/effect-asset.ts | 4 +- cocos/gfx/base/shader.ts | 4 + cocos/gfx/webgl/webgl-command-buffer.ts | 7 +- cocos/rendering/custom/define.ts | 153 ++++- cocos/rendering/custom/executor.ts | 62 +- cocos/rendering/custom/layout-graph-utils.ts | 261 ++++++--- cocos/rendering/custom/scene-culling.ts | 529 +++++++++++++++--- cocos/rendering/custom/web-pipeline-types.ts | 141 +++-- cocos/rendering/custom/web-pipeline.ts | 24 +- cocos/rendering/custom/web-program-library.ts | 165 ++++-- .../post-process/passes/forward-pass.ts | 14 +- .../post-process/utils/pass-context.ts | 53 +- .../rendering/render-additive-light-queue.ts | 2 +- 13 files changed, 1110 insertions(+), 309 deletions(-) diff --git a/cocos/asset/assets/effect-asset.ts b/cocos/asset/assets/effect-asset.ts index 06d4fac7039..95007cf7026 100644 --- a/cocos/asset/assets/effect-asset.ts +++ b/cocos/asset/assets/effect-asset.ts @@ -331,7 +331,9 @@ export class EffectAsset extends Asset { public onLoaded (): void { if (cclegacy.rendering && cclegacy.rendering.enableEffectImport) { addEffectDefaultProperties(this); - (cclegacy.rendering.programLib as ProgramLibrary).addEffect(this); + const programLib = cclegacy.rendering.programLib; + programLib.addEffect(this); + programLib.init(deviceManager.gfxDevice); } else { programLib.register(this); } diff --git a/cocos/gfx/base/shader.ts b/cocos/gfx/base/shader.ts index 64b99ec041f..23554d40d22 100644 --- a/cocos/gfx/base/shader.ts +++ b/cocos/gfx/base/shader.ts @@ -45,6 +45,10 @@ export abstract class Shader extends GFXObject { return this._samplers; } + get stages (): ShaderStage[] { + return this._stages; + } + protected _name = ''; protected _stages: ShaderStage[] = []; protected _attributes: Attribute[] = []; diff --git a/cocos/gfx/webgl/webgl-command-buffer.ts b/cocos/gfx/webgl/webgl-command-buffer.ts index f4868493ec3..c41205649d3 100644 --- a/cocos/gfx/webgl/webgl-command-buffer.ts +++ b/cocos/gfx/webgl/webgl-command-buffer.ts @@ -405,10 +405,13 @@ export class WebGLCommandBuffer extends CommandBuffer { } } - public pipelineBarrier (GeneralBarrier: Readonly, bufferBarriers?: Readonly, + public pipelineBarrier ( + GeneralBarrier: Readonly, + bufferBarriers?: Readonly, buffers?: Readonly, textureBarriers?: Readonly, - textures?: Readonly): void {} + textures?: Readonly, + ): void {} protected bindStates (): void { const bindStatesCmd = this._cmdAllocator.bindStatesCmdPool.alloc(WebGLCmdBindStates); diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index 3efcd29a768..50f7a8a0b39 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -24,17 +24,17 @@ import { EDITOR } from 'internal:constants'; import { BufferInfo, Buffer, BufferUsageBit, ClearFlagBit, Color, DescriptorSet, LoadOp, - Format, Rect, Sampler, StoreOp, Texture, Viewport, MemoryUsageBit, Filter, Address } from '../../gfx'; + Format, Rect, Sampler, StoreOp, Texture, Viewport, MemoryUsageBit, Filter, Address, DescriptorSetLayoutInfo, DescriptorSetLayoutBinding } from '../../gfx'; import { ProbeType, ReflectionProbe } from '../../render-scene/scene/reflection-probe'; import { Camera, SKYBOX_FLAG } from '../../render-scene/scene/camera'; -import { CSMLevel, ShadowType } from '../../render-scene/scene/shadows'; +import { CSMLevel, ShadowType, Shadows } from '../../render-scene/scene/shadows'; import { Light, LightType } from '../../render-scene/scene/light'; import { DirectionalLight } from '../../render-scene/scene/directional-light'; import { RangedDirectionalLight } from '../../render-scene/scene/ranged-directional-light'; import { PointLight } from '../../render-scene/scene/point-light'; import { SphereLight } from '../../render-scene/scene/sphere-light'; import { SpotLight } from '../../render-scene/scene/spot-light'; -import { supportsR32FloatTexture, supportsRGBA16HalfFloatTexture } from '../define'; +import { UBOForwardLight, supportsR32FloatTexture, supportsRGBA16HalfFloatTexture } from '../define'; import { BasicPipeline, Pipeline } from './pipeline'; import { AccessType, AttachmentType, CopyPair, LightInfo, @@ -46,7 +46,7 @@ import { getProfilerCamera, SRGBToLinear } from '../pipeline-funcs'; import { RenderWindow } from '../../render-scene/core/render-window'; import { RenderData, RenderGraph } from './render-graph'; import { WebComputePassBuilder, WebPipeline } from './web-pipeline'; -import { DescriptorSetData, LayoutGraph, LayoutGraphData } from './layout-graph'; +import { DescriptorSetData, DescriptorSetLayoutData, LayoutGraph, LayoutGraphData } from './layout-graph'; import { AABB } from '../../core/geometry'; import { DebugViewCompositeType, DebugViewSingleType } from '../debug-view'; import { ReflectionProbeManager } from '../../3d/reflection-probe/reflection-probe-manager'; @@ -2474,6 +2474,140 @@ export function bool (val): boolean { return !!val; } +export function AlignUp (value: number, alignment: number): number { + return (value + (alignment - 1)) & ~(alignment - 1); +} +const kLightMeterScale = 10000; +export function SetLightUBO ( + light: Light | null, + bHDR: boolean, + exposure: number, + shadowInfo: Shadows | null, + buffer: Float32Array, + offset: number, + elemSize: number, +): void { + const vec4Array = new Float32Array(4); + let size = 0.0; + let range = 0.0; + let luminanceHDR = 0.0; + let luminanceLDR = 0.0; + + if (light && light.type === LightType.SPHERE) { + const sphereLight = light as SphereLight; + vec4Array[0] = sphereLight.position.x; + vec4Array[1] = sphereLight.position.y; + vec4Array[2] = sphereLight.position.z; + vec4Array[3] = LightType.SPHERE; + size = sphereLight.size; + range = sphereLight.range; + luminanceHDR = sphereLight.luminanceHDR; + luminanceLDR = sphereLight.luminanceLDR; + } else if (light && light.type === LightType.SPOT) { + const spotLight = light as SpotLight; + vec4Array[0] = spotLight.position.x; + vec4Array[1] = spotLight.position.y; + vec4Array[2] = spotLight.position.z; + vec4Array[3] = LightType.SPOT; + size = spotLight.size; + range = spotLight.range; + luminanceHDR = spotLight.luminanceHDR; + luminanceLDR = spotLight.luminanceLDR; + } else if (light && light.type === LightType.POINT) { + const pointLight = light as PointLight; + vec4Array[0] = pointLight.position.x; + vec4Array[1] = pointLight.position.y; + vec4Array[2] = pointLight.position.z; + vec4Array[3] = LightType.POINT; + size = 0.0; + range = pointLight.range; + luminanceHDR = pointLight.luminanceHDR; + luminanceLDR = pointLight.luminanceLDR; + } else if (light && light.type === LightType.RANGED_DIRECTIONAL) { + const rangedDirLight = light as RangedDirectionalLight; + vec4Array[0] = rangedDirLight.position.x; + vec4Array[1] = rangedDirLight.position.y; + vec4Array[2] = rangedDirLight.position.z; + vec4Array[3] = LightType.RANGED_DIRECTIONAL; + size = 0.0; + range = 0.0; + luminanceHDR = rangedDirLight.illuminanceHDR; + luminanceLDR = rangedDirLight.illuminanceLDR; + } + + let index = offset + UBOForwardLight.LIGHT_POS_OFFSET; + buffer.set(vec4Array, index); + + index = offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET; + vec4Array.set([size, range, 0, 0]); + buffer.set(vec4Array, index); + + index = offset + UBOForwardLight.LIGHT_COLOR_OFFSET; + const color = light ? light.color : new Color(); + if (light && light.useColorTemperature) { + const tempRGB = light.colorTemperatureRGB; + buffer[index++] = color.x * tempRGB.x; + buffer[index++] = color.y * tempRGB.y; + buffer[index++] = color.z * tempRGB.z; + } else { + buffer[index++] = color.x; + buffer[index++] = color.y; + buffer[index++] = color.z; + } + + if (bHDR) { + buffer[index] = luminanceHDR * exposure * kLightMeterScale; + } else { + buffer[index] = luminanceLDR; + } + + switch (light ? light.type : LightType.UNKNOWN) { + case LightType.SPHERE: + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = 0; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0; + break; + case LightType.SPOT: { + const spotLight = light as SpotLight; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = spotLight.spotAngle; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = (shadowInfo && shadowInfo.enabled + && spotLight.shadowEnabled + && shadowInfo.type === ShadowType.ShadowMap) ? 1.0 : 0.0; + + index = offset + UBOForwardLight.LIGHT_DIR_OFFSET; + const direction = spotLight.direction; + buffer[index++] = direction.x; + buffer[index++] = direction.y; + buffer[index] = direction.z; + } break; + case LightType.POINT: + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = 0; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0; + break; + case LightType.RANGED_DIRECTIONAL: { + const rangedDirLight = light as RangedDirectionalLight; + const right = rangedDirLight.right; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 0] = right.x; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 1] = right.y; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 2] = right.z; + buffer[offset + UBOForwardLight.LIGHT_SIZE_RANGE_ANGLE_OFFSET + 3] = 0; + + const direction = rangedDirLight.direction; + buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 0] = direction.x; + buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 1] = direction.y; + buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 2] = direction.z; + buffer[offset + UBOForwardLight.LIGHT_DIR_OFFSET + 3] = 0; + + const scale = rangedDirLight.scale; + buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 0] = scale.x * 0.5; + buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 1] = scale.y * 0.5; + buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 2] = scale.z * 0.5; + buffer[offset + UBOForwardLight.LIGHT_BOUNDING_SIZE_VS_OFFSET + 3] = 0; + } break; + default: + break; + } +} + export function getSubpassOrPassID (sceneId: number, rg: RenderGraph, lg: LayoutGraphData): number { const queueId = rg.getParent(sceneId); assert(queueId !== 0xFFFFFFFF); @@ -2493,10 +2627,13 @@ export function getSubpassOrPassID (sceneId: number, rg: RenderGraph, lg: Layout assert(passLayoutId !== lg.nullVertex()); const subpassLayoutName: string = rg.getLayout(subpassOrPassID); - assert(!!subpassLayoutName); - const subpassLayoutId = lg.locateChild(passLayoutId, subpassLayoutName); - assert(subpassLayoutId !== lg.nullVertex()); - layoutId = subpassLayoutId; + if (subpassLayoutName.length === 0) { + layoutId = passLayoutId; + } else { + const subpassLayoutId = lg.locateChild(passLayoutId, subpassLayoutName); + assert(subpassLayoutId !== lg.nullVertex()); + layoutId = subpassLayoutId; + } } assert(layoutId !== lg.nullVertex()); return layoutId; diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index c2b3bd61379..5e450300d28 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -141,8 +141,9 @@ import { validPunctualLightsCulling, } from './define'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; -import { SceneCulling } from './scene-culling'; +import { LightResource, SceneCulling } from './scene-culling'; import { Pass } from '../../render-scene'; +import { WebProgramLibrary } from './web-program-library'; class ResourceVisitor implements ResourceGraphVisitor { name: string; @@ -1280,23 +1281,15 @@ class DeviceSceneTransversal extends WebSceneTransversal { } get graphScene (): GraphScene { return this._graphScene; } public preRenderPass (visitor: WebSceneVisitor): DevicePreSceneTask { - if (!this._preSceneTask) { - this._preSceneTask = new DevicePreSceneTask(this._currentQueue, this._graphScene, visitor); - } - this._preSceneTask.apply(this._currentQueue, this.graphScene); + this._preSceneTask = new DevicePreSceneTask(this._currentQueue, this._graphScene, visitor); return this._preSceneTask; } public transverse (visitor: WebSceneVisitor): DeviceSceneTask { - if (!this._sceneTask) { - this._sceneTask = new DeviceSceneTask(this._currentQueue, this._graphScene, visitor); - } - this._sceneTask.apply(this._currentQueue, this.graphScene); + this._sceneTask = new DeviceSceneTask(this._currentQueue, this._graphScene, visitor); return this._sceneTask; } public postRenderPass (visitor: WebSceneVisitor): DevicePostSceneTask { - if (!this._postSceneTask) { - this._postSceneTask = new DevicePostSceneTask(this._sceneData, context.ubo, this._camera, visitor); - } + this._postSceneTask = new DevicePostSceneTask(this._sceneData, context.ubo, this._camera, visitor); return this._postSceneTask; } } @@ -1372,17 +1365,9 @@ class DevicePreSceneTask extends WebSceneTask { public start (): void { if (this.graphScene.blit) { this._currentQueue.createBlitDesc(this.graphScene.blit); - return; - } - if (!this.camera) { - return; - } - const sceneFlag = this._graphScene.scene!.flags; - if (sceneFlag & SceneFlags.DEFAULT_LIGHTING) { - this._sceneCulling(); - validPunctualLightsCulling(context.pipeline, this.camera); - context.additiveLight.gatherLightPasses(this.camera, this._cmdBuff, this._currentQueue.devicePass.layoutName); } + context.lightResource.buildLightBuffer(context.commandBuffer); + context.lightResource.tryUpdateRenderSceneLocalDescriptorSet(context.culling); } public submit (): void { @@ -1562,14 +1547,6 @@ class DeviceSceneTask extends WebSceneTask { } } - private _recordAdditiveLights (): void { - context.additiveLight?.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } - public submit (): void { const devicePass = this._currentQueue.devicePass; const sceneCulling = context.culling; @@ -1580,21 +1557,10 @@ class DeviceSceneTask extends WebSceneTask { this._recordBlit(); return; } - const renderQueueDesc = sceneCulling.sceneQueryIndex.get(this.graphScene.sceneID)!; + const renderQueueDesc = sceneCulling.renderQueueIndex.get(this.graphScene.sceneID)!; const renderQueue = sceneCulling.renderQueues[renderQueueDesc.renderQueueTarget]; const graphSceneData = this.graphScene.scene!; - renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); - renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); - if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) { - this._recordAdditiveLights(); - this.visitor.bindDescriptorSet( - SetIndex.GLOBAL, - context.descriptorSet!, - ); - } - - renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); - renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); + renderQueue.recordCommands(context.commandBuffer, this._renderPass); if (bool(graphSceneData.flags & SceneFlags.REFLECTION_PROBE)) renderQueue.probeQueue.removeMacro(); if (graphSceneData.flags & SceneFlags.GEOMETRY) { this.camera!.geometryRenderer?.render( @@ -1877,6 +1843,7 @@ class ExecutorContext { for (const infoMap of this.submitMap) { for (const info of infoMap[1]) info[1].reset(); } + this.lightResource.clear(); } resize (width: number, height: number): void { this.width = width; @@ -1899,6 +1866,7 @@ class ExecutorContext { readonly pools: ExecutorPools; readonly blit: BlitInfo; readonly culling: SceneCulling; + lightResource: LightResource = new LightResource(); renderGraph: RenderGraph; width: number; height: number; @@ -1926,6 +1894,8 @@ export class Executor { width, height, ); + const programLib: WebProgramLibrary = cclegacy.rendering.programLib; + context.lightResource.init(programLib, device, 16); } resize (width: number, height: number): void { @@ -1979,8 +1949,10 @@ export class Executor { context.renderGraph = rg; context.reset(); const cmdBuff = context.commandBuffer; - context.culling.buildRenderQueues(rg, context.layoutGraph, context.pipelineSceneData); - context.culling.uploadInstancing(cmdBuff); + const culling = context.culling; + culling.buildRenderQueues(rg, context.layoutGraph, context.pipelineSceneData); + context.lightResource.buildLights(culling, context.pipelineSceneData.isHDR, context.pipelineSceneData.shadows); + culling.uploadInstancing(cmdBuff); this._removeDeviceResource(); cmdBuff.begin(); if (!this._visitor) this._visitor = new RenderVisitor(); diff --git a/cocos/rendering/custom/layout-graph-utils.ts b/cocos/rendering/custom/layout-graph-utils.ts index 6787df02880..99fa5da936c 100644 --- a/cocos/rendering/custom/layout-graph-utils.ts +++ b/cocos/rendering/custom/layout-graph-utils.ts @@ -24,8 +24,9 @@ /* eslint-disable max-len */ import { EffectAsset } from '../../asset/assets'; -import { assert } from '../../core'; -import { DescriptorSetInfo, DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutInfo, DescriptorType, Device, PipelineLayout, PipelineLayoutInfo, ShaderStageFlagBit, Type, Uniform, UniformBlock } from '../../gfx'; +import { assert, error, log, warn } from '../../core'; +import { DescriptorSetInfo, DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutInfo, DescriptorType, Device, Feature, Format, FormatFeatureBit, GetTypeSize, PipelineLayout, PipelineLayoutInfo, ShaderStageFlagBit, Type, Uniform, UniformBlock } from '../../gfx'; +import { UBOForwardLight, UBOSkinning } from '../define'; import { DefaultVisitor, depthFirstSearch, GraphColor, MutableVertexPropertyMap } from './graph'; import { DescriptorBlockData, DescriptorData, DescriptorDB, DescriptorSetData, DescriptorSetLayoutData, LayoutGraph, LayoutGraphData, LayoutGraphDataValue, LayoutGraphValue, PipelineLayoutData, RenderPassType, RenderPhase, RenderPhaseData, RenderStageData, ShaderProgramData } from './layout-graph'; import { UpdateFrequency, getUpdateFrequencyName, getDescriptorTypeOrderName, Descriptor, DescriptorBlock, DescriptorBlockFlattened, DescriptorBlockIndex, DescriptorTypeOrder, ParameterType } from './types'; @@ -109,7 +110,7 @@ export function getGfxDescriptorType (type: DescriptorTypeOrder): DescriptorType case DescriptorTypeOrder.INPUT_ATTACHMENT: return DescriptorType.INPUT_ATTACHMENT; default: - console.error('DescriptorType not found'); + error('DescriptorType not found'); return DescriptorType.INPUT_ATTACHMENT; } } @@ -137,7 +138,7 @@ export function getDescriptorTypeOrder (type: DescriptorType): DescriptorTypeOrd return DescriptorTypeOrder.INPUT_ATTACHMENT; case DescriptorType.UNKNOWN: default: - console.error('DescriptorTypeOrder not found'); + error('DescriptorTypeOrder not found'); return DescriptorTypeOrder.INPUT_ATTACHMENT; } } @@ -460,7 +461,7 @@ export class VisibilityBlock { public getVisibility (name: string): ShaderStageFlagBit { const v = this.descriptors.get(name); if (v === undefined) { - console.error(`Can't find visibility for descriptor: ${name}`); + error(`Can't find visibility for descriptor: ${name}`); return ShaderStageFlagBit.NONE; } return v; @@ -496,6 +497,50 @@ export class VisibilityPass { phases = new Map(); } +export const DEFAULT_UNIFORM_COUNTS: Map = new Map([ + ['cc_lightPos', UBOForwardLight.LIGHTS_PER_PASS], + ['cc_lightColor', UBOForwardLight.LIGHTS_PER_PASS], + ['cc_lightSizeRangeAngle', UBOForwardLight.LIGHTS_PER_PASS], + ['cc_lightDir', UBOForwardLight.LIGHTS_PER_PASS], + ['cc_lightBoundingSizeVS', UBOForwardLight.LIGHTS_PER_PASS], +]); + +export const DYNAMIC_UNIFORM_BLOCK: Set = new Set([ + 'CCCamera', + 'CCForwardLight', + 'CCUILocal', +]); + +export function getUniformBlockSize (blockMembers: Array): number { + let prevSize: number = 0; + + for (const m of blockMembers) { + if (m.count) { + prevSize += GetTypeSize(m.type) * m.count; + continue; + } + + const iter = DEFAULT_UNIFORM_COUNTS.get(m.name); + if (iter !== undefined) { + prevSize += GetTypeSize(m.type) * iter; + continue; + } + + if (m.name === 'cc_joints') { + const sz = GetTypeSize(m.type) * UBOSkinning.LAYOUT.members[0].count; + assert(sz !== UBOSkinning.SIZE); + prevSize += sz; + continue; + } + + error(`Invalid uniform count: ${m.name}`); + } + + assert(!!prevSize); + + return prevSize; +} + export class VisibilityGraph { public getPass (passName: string): VisibilityPass { const pass = this.passes.get(passName); @@ -542,7 +587,7 @@ export class VisibilityGraph { continue; } if (shader.descriptors === undefined) { - console.warn(`No descriptors in shader: ${programName}, please reimport ALL effects`); + warn(`No descriptors in shader: ${programName}, please reimport ALL effects`); continue; } const passName = getPassName(pass); @@ -595,8 +640,10 @@ export class LayoutGraphInfo { let passID = lg.locateChild(lg.nullVertex(), passName); if (passID === lg.nullVertex()) { passID = lg.addVertex( - LayoutGraphValue.RenderStage, type, - passName, new DescriptorDB(), + LayoutGraphValue.RenderStage, + type, + passName, + new DescriptorDB(), lg.nullVertex(), ); } @@ -608,8 +655,10 @@ export class LayoutGraphInfo { let subpassID = lg.locateChild(passID, subpassName); if (subpassID === lg.nullVertex()) { subpassID = lg.addVertex( - LayoutGraphValue.RenderStage, RenderPassType.RENDER_SUBPASS, - subpassName, new DescriptorDB(), + LayoutGraphValue.RenderStage, + RenderPassType.RENDER_SUBPASS, + subpassName, + new DescriptorDB(), passID, ); } @@ -621,8 +670,10 @@ export class LayoutGraphInfo { let phaseID = lg.locateChild(subpassOrPassID, phaseName); if (phaseID === lg.nullVertex()) { phaseID = lg.addVertex( - LayoutGraphValue.RenderPhase, new RenderPhase(), - phaseName, new DescriptorDB(), + LayoutGraphValue.RenderPhase, + new RenderPhase(), + phaseName, + new DescriptorDB(), subpassOrPassID, ); } @@ -675,18 +726,21 @@ export class LayoutGraphInfo { return; } if (value.type !== type) { - console.warn(`Type mismatch for descriptor ${name}`); + warn(`Type mismatch for descriptor ${name}`); } } - private addUniformBlock (block: DescriptorBlock, - name: string, gfxBlock: UniformBlock): void { + private addUniformBlock ( + block: DescriptorBlock, + name: string, + gfxBlock: UniformBlock, + ): void { const value = block.uniformBlocks.get(name); if (value === undefined) { block.uniformBlocks.set(name, gfxBlock); return; } if (!this.checkConsistency(value, gfxBlock)) { - console.warn(`Uniform block ${name} is inconsistent in the same block`); + warn(`Uniform block ${name} is inconsistent in the same block`); } } private buildBlocks (visDB: VisibilityDB, rate: UpdateFrequency, blocks: EffectAsset.IBlockInfo[], db: DescriptorDB, counter: DescriptorCounter): void { @@ -716,7 +770,9 @@ export class LayoutGraphInfo { visDB: VisibilityDB, rate: UpdateFrequency, infoArray: EffectAsset.IBufferInfo[], - type: Type, db: DescriptorDB, counter: DescriptorCounter, + type: Type, + db: DescriptorDB, + counter: DescriptorCounter, ): void { const visBlock = visDB.getBlock({ updateFrequency: rate, @@ -744,7 +800,9 @@ export class LayoutGraphInfo { rate: UpdateFrequency, order: DescriptorTypeOrder, infoArray: EffectAsset.ISamplerInfo[] | EffectAsset.IInputAttachmentInfo[], - type: Type, db: DescriptorDB, counter: DescriptorCounter, + type: Type, + db: DescriptorDB, + counter: DescriptorCounter, ): void { const visBlock = visDB.getBlock({ updateFrequency: rate, @@ -772,7 +830,8 @@ export class LayoutGraphInfo { rate: UpdateFrequency, order: DescriptorTypeOrder, infoArray: EffectAsset.IImageInfo[] | EffectAsset.ISamplerTextureInfo[] | EffectAsset.ITextureInfo[], - db: DescriptorDB, counter: DescriptorCounter, + db: DescriptorDB, + counter: DescriptorCounter, ): void { const visBlock = visDB.getBlock({ updateFrequency: rate, @@ -807,11 +866,11 @@ export class LayoutGraphInfo { } } if (!shader) { - console.warn(`program: ${programName} not found`); + warn(`program: ${programName} not found`); continue; } if (shader.descriptors === undefined) { - console.warn(`No descriptors in shader: ${programName}, please reimport ALL effects`); + warn(`No descriptors in shader: ${programName}, please reimport ALL effects`); continue; } // get database @@ -872,13 +931,13 @@ export class LayoutGraphInfo { const phaseID = v; const parentID = lg.getParent(phaseID); if (lg.id(parentID) !== LayoutGraphValue.RenderStage) { - console.error(`phase: ${lg.getName(phaseID)} has no parent stage`); + error(`phase: ${lg.getName(phaseID)} has no parent stage`); return 1; } const phaseDB = lg.getDescriptors(phaseID); const passVisDB = visMap.get(parentID); if (!passVisDB) { - console.error(`pass: ${lg.getName(parentID)} has no visibility database`); + error(`pass: ${lg.getName(parentID)} has no visibility database`); return 1; } // merge phase visibility to pass visibility @@ -902,14 +961,14 @@ export class LayoutGraphInfo { const phaseID = v; const parentID = lg.getParent(phaseID); if (lg.id(parentID) !== LayoutGraphValue.RenderStage) { - console.error(`phase: ${lg.getName(phaseID)} has no parent stage`); + error(`phase: ${lg.getName(phaseID)} has no parent stage`); return 1; } const passDB = lg.getDescriptors(parentID); const phaseDB = lg.getDescriptors(phaseID); const passVisDB = visMap.get(parentID); if (passVisDB === undefined) { - console.error(`pass: ${lg.getName(parentID)} has no visibility database`); + error(`pass: ${lg.getName(parentID)} has no visibility database`); return 1; } for (const [key0, block] of phaseDB.blocks) { @@ -917,9 +976,7 @@ export class LayoutGraphInfo { if (index0.updateFrequency <= UpdateFrequency.PER_PHASE) { continue; } - const visIndex = new VisibilityIndex( - index0.updateFrequency, index0.parameterType, index0.descriptorType, - ); + const visIndex = new VisibilityIndex(index0.updateFrequency, index0.parameterType, index0.descriptorType); const passVisBlock = passVisDB.getBlock(visIndex); for (const [name, d] of block.descriptors) { @@ -943,7 +1000,7 @@ export class LayoutGraphInfo { } const b = block.uniformBlocks.get(name); if (!b) { - console.error(`uniform block: ${name} not found`); + error(`uniform block: ${name} not found`); return 1; } this.addUniformBlock(passBlock, name, b); @@ -968,22 +1025,22 @@ export class LayoutGraphInfo { for (const e of lg.children(passID)) { const phaseID = lg.child(e); if (lg.id(phaseID) !== LayoutGraphValue.RenderPhase) { - console.error(`pass: ${lg.getName(passID)} is not single_render_pass or render_subpass`); + error(`pass: ${lg.getName(passID)} is not single_render_pass or render_subpass`); return 1; } const phaseDB = lg.getDescriptors(phaseID); for (const [key, passBlock] of passDB.blocks) { const index: DescriptorBlockIndex = JSON.parse(key); if (index.updateFrequency !== UpdateFrequency.PER_PASS) { - console.error(`phase: ${lg.getName(phaseID)} update frequency is not PER_PASS`); + error(`phase: ${lg.getName(phaseID)} update frequency is not PER_PASS`); return 1; } if (passBlock.count === 0) { - console.error(`pass: ${lg.getName(passID)} count is 0`); + error(`pass: ${lg.getName(passID)} count is 0`); return 1; } if (passBlock.capacity !== passBlock.count) { - console.error(`pass: ${lg.getName(passID)} capacity does not equal count`); + error(`pass: ${lg.getName(passID)} capacity does not equal count`); return 1; } const phaseBlock = this.getDescriptorBlock(key, phaseDB); @@ -1047,7 +1104,7 @@ function buildLayoutGraphDataImpl (graph: LayoutGraph, builder: LayoutGraphBuild } const vertID = builder.addRenderStage(graph.getName(v), parentID); if (vertID !== v) { - console.error('vertex id mismatch'); + error('vertex id mismatch'); } minLevel = UpdateFrequency.PER_PASS; maxLevel = UpdateFrequency.PER_PASS; @@ -1059,7 +1116,7 @@ function buildLayoutGraphDataImpl (graph: LayoutGraph, builder: LayoutGraphBuild assert(parentType === RenderPassType.RENDER_SUBPASS || parentType === RenderPassType.SINGLE_RENDER_PASS); const vertID = builder.addRenderPhase(graph.getName(v), parentID); if (vertID !== v) { - console.error('vertex id mismatch'); + error('vertex id mismatch'); } const phase = graph.getRenderPhase(v); for (const shaderName of phase.shaders) { @@ -1070,7 +1127,7 @@ function buildLayoutGraphDataImpl (graph: LayoutGraph, builder: LayoutGraphBuild break; } default: - console.error('unknown vertex type'); + error('unknown vertex type'); minLevel = UpdateFrequency.PER_INSTANCE; minLevel = UpdateFrequency.PER_PASS; break; @@ -1092,7 +1149,7 @@ function buildLayoutGraphDataImpl (graph: LayoutGraph, builder: LayoutGraphBuild } const flattened = convertDescriptorBlock(block); if (block.capacity === 0) { - console.error('block capacity is 0'); + error('block capacity is 0'); return; } if (index.updateFrequency > UpdateFrequency.PER_BATCH) { @@ -1141,16 +1198,24 @@ class LayoutGraphBuilder2 { addRenderStage (name: string, parentID: number): number { return this.lg.addVertex( LayoutGraphDataValue.RenderStage, - new RenderStageData(), name, - UpdateFrequency.PER_PASS, new PipelineLayoutData(), + new RenderStageData(), + + name, + UpdateFrequency.PER_PASS, + + new PipelineLayoutData(), parentID, ); } addRenderPhase (name: string, parentID: number): number { return this.lg.addVertex( LayoutGraphDataValue.RenderPhase, - new RenderPhaseData(), name, - UpdateFrequency.PER_PHASE, new PipelineLayoutData(), + new RenderPhaseData(), + + name, + UpdateFrequency.PER_PHASE, + + new PipelineLayoutData(), parentID, ); } @@ -1176,20 +1241,20 @@ class LayoutGraphBuilder2 { } addDescriptorBlock (nodeID: number, index: DescriptorBlockIndex, block: Readonly): void { if (block.capacity <= 0) { - console.error('empty block'); + error('empty block'); return; } if (block.descriptorNames.length !== block.descriptors.length) { - console.error('error descriptor'); + error('error descriptor'); return; } if (block.uniformBlockNames.length !== block.uniformBlocks.length) { - console.error('error uniform'); + error('error uniform'); return; } if (!(index.updateFrequency >= UpdateFrequency.PER_INSTANCE && index.updateFrequency <= UpdateFrequency.PER_PASS)) { - console.error('invalid update frequency'); + error('invalid update frequency'); return; } @@ -1230,7 +1295,7 @@ class LayoutGraphBuilder2 { } reserveDescriptorBlock (nodeID: number, index: DescriptorBlockIndex, block: DescriptorBlockFlattened): void { if (block.capacity <= 0) { - console.error('empty block'); + error('empty block'); return; } const g: LayoutGraphData = this.lg; @@ -1337,9 +1402,12 @@ function getDescriptorBlockData (map: Map, index: D } // make DescriptorSetLayoutData from effect directly -export function makeDescriptorSetLayoutData (lg: LayoutGraphData, - rate: UpdateFrequency, set: number, - descriptors: EffectAsset.IDescriptorInfo): DescriptorSetLayoutData { +export function makeDescriptorSetLayoutData ( + lg: LayoutGraphData, + rate: UpdateFrequency, + set: number, + descriptors: EffectAsset.IDescriptorInfo, +): DescriptorSetLayoutData { const map = new Map(); const uniformBlocks: Map = new Map(); for (let i = 0; i < descriptors.blocks.length; i++) { @@ -1435,7 +1503,7 @@ export function makeDescriptorSetLayoutData (lg: LayoutGraphData, // update uniform buffer binding const ub = uniformBlocks.get(d.descriptorID); if (!ub) { - console.error(`Uniform block not found for ${d.descriptorID}`); + error(`Uniform block not found for ${d.descriptorID}`); continue; } assert(ub.binding === 0xFFFFFFFF); @@ -1446,7 +1514,7 @@ export function makeDescriptorSetLayoutData (lg: LayoutGraphData, // update block capacity const binding = data.bindingMap.get(d.descriptorID); if (binding !== undefined) { - console.error(`Duplicated descriptor ${d.descriptorID}`); + error(`Duplicated descriptor ${d.descriptorID}`); } data.bindingMap.set(d.descriptorID, block.offset + block.capacity); block.capacity += d.count; @@ -1466,8 +1534,10 @@ export function makeDescriptorSetLayoutData (lg: LayoutGraphData, } // fill DescriptorSetLayoutInfo from DescriptorSetLayoutData -export function initializeDescriptorSetLayoutInfo (layoutData: DescriptorSetLayoutData, - info: DescriptorSetLayoutInfo): void { +export function initializeDescriptorSetLayoutInfo ( + layoutData: DescriptorSetLayoutData, + info: DescriptorSetLayoutInfo, +): void { for (let i = 0; i < layoutData.descriptorBlocks.length; ++i) { const block = layoutData.descriptorBlocks[i]; let slot = block.offset; @@ -1488,8 +1558,11 @@ export function initializeDescriptorSetLayoutInfo (layoutData: DescriptorSetLayo let _emptyDescriptorSetLayout: DescriptorSetLayout; let _emptyPipelineLayout: PipelineLayout; -function populatePipelineLayoutInfo (layout: PipelineLayoutData, - rate: UpdateFrequency, info: PipelineLayoutInfo): void { +export function populatePipelineLayoutInfo ( + layout: PipelineLayoutData, + rate: UpdateFrequency, + info: PipelineLayoutInfo, +): void { const set = layout.descriptorSets.get(rate); if (set && set.descriptorSetLayout) { info.setLayouts.push(set.descriptorSetLayout); @@ -1498,6 +1571,19 @@ function populatePipelineLayoutInfo (layout: PipelineLayoutData, } } +export function generateConstantMacros (device: Device, constantMacros: string): void { + constantMacros = ` + #define CC_DEVICE_SUPPORT_FLOAT_TEXTURE ${device.getFormatFeatures(Format.RGBA32F) & ( + FormatFeatureBit.RENDER_TARGET | FormatFeatureBit.SAMPLED_TEXTURE + ) ? '1' : '0'} + #define CC_DEVICE_MAX_VERTEX_UNIFORM_VECTORS ${device.capabilities.maxVertexUniformVectors} + #define CC_DEVICE_MAX_FRAGMENT_UNIFORM_VECTORS ${device.capabilities.maxFragmentUniformVectors} + #define CC_DEVICE_CAN_BENEFIT_FROM_INPUT_ATTACHMENT ${device.hasFeature(Feature.INPUT_ATTACHMENT_BENEFIT) ? '1' : '0'} + #define CC_PLATFORM_ANDROID_AND_WEBGL 0 + #define CC_ENABLE_WEBGL_HIGHP_STRUCT_VALUES 0 + #define CC_JOINT_UNIFORM_CAPACITY ${UBOSkinning.JOINT_UNIFORM_CAPACITY}`; +} + // initialize layout graph module export function initializeLayoutGraphData (device: Device, lg: LayoutGraphData): void { // create descriptor sets @@ -1507,10 +1593,12 @@ export function initializeLayoutGraphData (device: Device, lg: LayoutGraphData): const layoutData = lg.getLayout(v); for (const [_, set] of layoutData.descriptorSets) { if (set.descriptorSetLayout !== null) { - console.warn('descriptor set layout already initialized. It will be overwritten'); + warn('descriptor set layout already initialized. It will be overwritten'); } - initializeDescriptorSetLayoutInfo(set.descriptorSetLayoutData, - set.descriptorSetLayoutInfo); + initializeDescriptorSetLayoutInfo( + set.descriptorSetLayoutData, + set.descriptorSetLayoutInfo, + ); set.descriptorSetLayout = device.createDescriptorSetLayout(set.descriptorSetLayoutInfo); } } @@ -1558,14 +1646,18 @@ export function getEmptyPipelineLayout (): PipelineLayout { } // get descriptor set from LayoutGraphData (not from ProgramData) -export function getOrCreateDescriptorSetLayout (lg: LayoutGraphData, - subpassOrPassID: number, phaseID: number, rate: UpdateFrequency): DescriptorSetLayout { +export function getOrCreateDescriptorSetLayout ( + lg: LayoutGraphData, + subpassOrPassID: number, + phaseID: number, + rate: UpdateFrequency, +): DescriptorSetLayout { if (rate < UpdateFrequency.PER_PASS) { const phaseData = lg.getLayout(phaseID); const data = phaseData.descriptorSets.get(rate); if (data) { if (!data.descriptorSetLayout) { - console.error('descriptor set layout not initialized'); + error('descriptor set layout not initialized'); return _emptyDescriptorSetLayout; } return data.descriptorSetLayout; @@ -1580,7 +1672,7 @@ export function getOrCreateDescriptorSetLayout (lg: LayoutGraphData, const data = passData.descriptorSets.get(rate); if (data) { if (!data.descriptorSetLayout) { - console.error('descriptor set layout not initialized'); + error('descriptor set layout not initialized'); return _emptyDescriptorSetLayout; } return data.descriptorSetLayout; @@ -1589,14 +1681,18 @@ export function getOrCreateDescriptorSetLayout (lg: LayoutGraphData, } // getDescriptorSetLayout from LayoutGraphData -export function getDescriptorSetLayout (lg: LayoutGraphData, - subpassOrPassID: number, phaseID: number, rate: UpdateFrequency): DescriptorSetLayout | null { +export function getDescriptorSetLayout ( + lg: LayoutGraphData, + subpassOrPassID: number, + phaseID: number, + rate: UpdateFrequency, +): DescriptorSetLayout | null { if (rate < UpdateFrequency.PER_PASS) { const phaseData = lg.getLayout(phaseID); const data = phaseData.descriptorSets.get(rate); if (data) { if (!data.descriptorSetLayout) { - console.error('descriptor set layout not initialized'); + error('descriptor set layout not initialized'); return null; } return data.descriptorSetLayout; @@ -1611,7 +1707,7 @@ export function getDescriptorSetLayout (lg: LayoutGraphData, const data = passData.descriptorSets.get(rate); if (data) { if (!data.descriptorSetLayout) { - console.error('descriptor set layout not initialized'); + error('descriptor set layout not initialized'); return null; } return data.descriptorSetLayout; @@ -1620,8 +1716,11 @@ export function getDescriptorSetLayout (lg: LayoutGraphData, } // get or create DescriptorBlockData from DescriptorSetLayoutData -export function getOrCreateDescriptorBlockData (data: DescriptorSetLayoutData, - type: DescriptorType, vis: ShaderStageFlagBit): DescriptorBlockData { +export function getOrCreateDescriptorBlockData ( + data: DescriptorSetLayoutData, + type: DescriptorType, + vis: ShaderStageFlagBit, +): DescriptorBlockData { const order = getDescriptorTypeOrder(type); for (const block of data.descriptorBlocks) { if (block.type === order && block.visibility === vis) { @@ -1658,8 +1757,10 @@ export function getDescriptorName (lg: LayoutGraphData, nameID: number): string return lg.valueNames[nameID]; } -export function getPerPassDescriptorSetLayoutData (lg: LayoutGraphData, - subpassOrPassID: number): DescriptorSetLayoutData | null { +export function getPerPassDescriptorSetLayoutData ( + lg: LayoutGraphData, + subpassOrPassID: number, +): DescriptorSetLayoutData | null { assert(subpassOrPassID !== lg.nullVertex()); const node = lg.getLayout(subpassOrPassID); const set = node.descriptorSets.get(UpdateFrequency.PER_PASS); @@ -1669,8 +1770,10 @@ export function getPerPassDescriptorSetLayoutData (lg: LayoutGraphData, return set.descriptorSetLayoutData; } -export function getPerPhaseDescriptorSetLayoutData (lg: LayoutGraphData, - phaseID: number): DescriptorSetLayoutData | null { +export function getPerPhaseDescriptorSetLayoutData ( + lg: LayoutGraphData, + phaseID: number, +): DescriptorSetLayoutData | null { assert(phaseID !== lg.nullVertex()); const node = lg.getLayout(phaseID); const set = node.descriptorSets.get(UpdateFrequency.PER_PHASE); @@ -1680,8 +1783,11 @@ export function getPerPhaseDescriptorSetLayoutData (lg: LayoutGraphData, return set.descriptorSetLayoutData; } -export function getPerBatchDescriptorSetLayoutData (lg: LayoutGraphData, - phaseID: number, programID): DescriptorSetLayoutData | null { +export function getPerBatchDescriptorSetLayoutData ( + lg: LayoutGraphData, + phaseID: number, + programID, +): DescriptorSetLayoutData | null { assert(phaseID !== lg.nullVertex()); const phase = lg.getRenderPhase(phaseID); assert(programID < phase.shaderPrograms.length); @@ -1693,8 +1799,11 @@ export function getPerBatchDescriptorSetLayoutData (lg: LayoutGraphData, return set.descriptorSetLayoutData; } -export function getPerInstanceDescriptorSetLayoutData (lg: LayoutGraphData, - phaseID: number, programID): DescriptorSetLayoutData | null { +export function getPerInstanceDescriptorSetLayoutData ( + lg: LayoutGraphData, + phaseID: number, + programID, +): DescriptorSetLayoutData | null { assert(phaseID !== lg.nullVertex()); const phase = lg.getRenderPhase(phaseID); assert(programID < phase.shaderPrograms.length); diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 8a8e001ab93..5ab7d58739e 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -1,22 +1,25 @@ import { Vec3, assert, RecyclePool } from '../../core'; import { Frustum, intersect, AABB } from '../../core/geometry'; -import { CommandBuffer } from '../../gfx'; +import { CommandBuffer, Device, Buffer, BufferInfo, BufferViewInfo, MemoryUsageBit, BufferUsageBit } from '../../gfx'; import { BatchingSchemes, Pass, RenderScene } from '../../render-scene'; -import { CSMLevel, Camera, DirectionalLight, LightType, Model, ProbeType, - ReflectionProbe, SKYBOX_FLAG, ShadowType, SpotLight } from '../../render-scene/scene'; +import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, PointLight, ProbeType, + RangedDirectionalLight, + ReflectionProbe, SKYBOX_FLAG, ShadowType, Shadows, SphereLight, SpotLight } from '../../render-scene/scene'; import { Layers, Node } from '../../scene-graph'; import { PipelineSceneData } from '../pipeline-scene-data'; -import { hashCombineStr, getSubpassOrPassID, bool } from './define'; +import { hashCombineStr, getSubpassOrPassID, bool, AlignUp, SetLightUBO } from './define'; import { LayoutGraphData } from './layout-graph'; -import { RenderGraph, RenderGraphValue, SceneData } from './render-graph'; +import { CullingFlags, RenderGraph, RenderGraphValue, SceneData } from './render-graph'; import { SceneFlags } from './types'; import { RenderQueue, RenderQueueDesc, instancePool } from './web-pipeline-types'; import { ObjectPool } from './utils'; +import { getUniformBlockSize } from './layout-graph-utils'; +import { WebProgramLibrary } from './web-program-library'; const vec3Pool = new ObjectPool(() => new Vec3()); class CullingPools { - cullingKeyRecycle = new RecyclePool(() => new CullingKey(), 8); - cullingQueriesRecycle = new RecyclePool(() => new CullingQueries(), 8); + frustumCullingKeyRecycle = new RecyclePool(() => new FrustumCullingKey(), 8); + frustumCullingsRecycle = new RecyclePool(() => new FrustumCulling(), 8); renderQueueRecycle = new RecyclePool(() => new RenderQueue(), 8); renderQueueDescRecycle = new RecyclePool(() => new RenderQueueDesc(), 8); } @@ -27,12 +30,15 @@ const REFLECTION_PROBE_DEFAULT_MASK = Layers.makeMaskExclude([Layers.BitMask.UI_ function computeCullingKey ( sceneData: SceneData, castShadows: boolean, + refId: number = -1, ): number { let hashCode = 0; const camera = sceneData.camera; const light = sceneData.light.light; const lightLevel = sceneData.light.level; + const culledByLight = sceneData.light.culledByLight; const reflectProbe = sceneData.light.probe; + const shadeLight = sceneData.shadingLight; if (camera) { // camera hashCode = hashCombineStr(`u${camera.node.uuid}`, hashCode); @@ -67,15 +73,20 @@ function computeCullingKey ( // default: // } } + if (shadeLight) { + hashCode = hashCombineStr(`shadeLight${shadeLight.node!.uuid}`, hashCode); + } + hashCode = hashCombineStr(`culledByLight${culledByLight}`, hashCode); hashCode = hashCombineStr(`cast${castShadows}`, hashCode); hashCode = hashCombineStr(`level${lightLevel}`, hashCode); if (reflectProbe) { hashCode = hashCombineStr(`probe${reflectProbe.getProbeId()}`, hashCode); } + hashCode = hashCombineStr(`refId${refId}`, hashCode); return hashCode; } -class CullingKey { +class FrustumCullingKey { sceneData: SceneData | null = null; castShadows = false; constructor (sceneData: SceneData | null = null, castShadows: boolean = false) { @@ -88,15 +99,45 @@ class CullingKey { } } +class LightBoundsCullingKey { + sceneData: SceneData | null = null; + frustumCullingID: FrustumCullingID = -1; + constructor (sceneData: SceneData | null = null, frustumCullingID: FrustumCullingID = -1) { + this.sceneData = sceneData; + this.frustumCullingID = frustumCullingID; + } + update (sceneData: SceneData | null = null, frustumCullingID: FrustumCullingID = -1): void { + this.sceneData = sceneData; + this.frustumCullingID = frustumCullingID; + } +} + +class LightBoundsCulling { + resultKeyIndex: Map = new Map(); + resultIndex: Map = new Map(); + update (): void { + this.resultIndex.clear(); + this.resultKeyIndex.clear(); + } +} + +class LightBoundsCullingResult { + instances: Array = new Array(); + lightByteOffset: number = 0xFFFFFFFF; +} + +type FrustumCullingID = number; +type LightBoundsCullingID = number; + let pSceneData: PipelineSceneData; -class CullingQueries { +class FrustumCulling { // key: hash val - culledResultIndex: Map = new Map(); - cullingKeyResult: Map = new Map(); + resultIndex: Map = new Map(); + resultKeyIndex: Map = new Map(); update (): void { - this.culledResultIndex.clear(); - this.cullingKeyResult.clear(); + this.resultIndex.clear(); + this.resultKeyIndex.clear(); } } @@ -136,7 +177,6 @@ function sceneCulling ( camOrLightFrustum: Readonly, castShadow: boolean, probe: ReflectionProbe | null, - isReflectProbe: boolean, models: Array, ): void { const skybox = pSceneData.skybox; @@ -242,12 +282,10 @@ function addRenderObject ( // add object to queue if (pass.batchingScheme === BatchingSchemes.INSTANCING) { - const instancedBuffer = pass.getInstancedBuffer(); - instancedBuffer.merge(subModel, passIdx); if (is_blend) { - queue.transparentInstancingQueue.add(instancedBuffer); + queue.transparentInstancingQueue.add(pass, subModel, passIdx); } else { - queue.opaqueInstancingQueue.add(instancedBuffer); + queue.opaqueInstancingQueue.add(pass, subModel, passIdx); } } else { const depth = computeSortingDepth(camera, model); @@ -262,31 +300,37 @@ function addRenderObject ( } export class SceneCulling { - sceneQueries: Map = new Map(); - culledResults: Array> = new Array>(); + frustumCullings: Map = new Map(); + frustumCullingResults: Array> = new Array>(); + lightBoundsCullings: Map = new Map(); + lightBoundsCullingResults: Array = new Array(); renderQueues: Array = new Array(); - sceneQueryIndex: Map = new Map(); + renderQueueIndex: Map = new Map(); cullingPools = new CullingPools(); // source id - numCullingQueries = 0; + numFrustumCulling = 0; + numLightBoundsCulling = 0; // target id numRenderQueues = 0; layoutGraph; renderGraph; resetPool (): void { - this.cullingPools.cullingKeyRecycle.reset(); - this.cullingPools.cullingQueriesRecycle.reset(); + this.cullingPools.frustumCullingKeyRecycle.reset(); + this.cullingPools.frustumCullingsRecycle.reset(); this.cullingPools.renderQueueRecycle.reset(); this.cullingPools.renderQueueDescRecycle.reset(); instancePool.reset(); } clear (): void { this.resetPool(); - this.sceneQueries.clear(); - this.culledResults.length = 0; + this.frustumCullings.clear(); + this.frustumCullingResults.length = 0; + this.lightBoundsCullings.clear(); + this.lightBoundsCullingResults.length = 0; this.renderQueues.length = 0; - this.sceneQueryIndex.clear(); - this.numCullingQueries = 0; + this.renderQueueIndex.clear(); + this.numLightBoundsCulling = 0; + this.numFrustumCulling = 0; this.numRenderQueues = 0; } @@ -295,39 +339,78 @@ export class SceneCulling { this.renderGraph = rg; pSceneData = pplSceneData; this.collectCullingQueries(rg, lg); - this.batchCulling(pplSceneData); + this.batchFrustumCulling(pplSceneData); + this.batchLightBoundsCulling(); this.fillRenderQueues(rg, pplSceneData); } - private getOrCreateSceneCullingQuery (sceneId: number): number { + private getOrCreateLightBoundsCulling (sceneData: SceneData, frustumCullingID: FrustumCullingID): LightBoundsCullingID { + if (!(sceneData.cullingFlags & CullingFlags.LIGHT_BOUNDS)) { + return 0xFFFFFFFF; // Return an empty ID. + } + assert(!!sceneData.shadingLight, 'shadingLight is expected but not found.'); + const scene = sceneData.scene; + assert(!!scene, 'scene is expected but not found.'); + + let queries = this.lightBoundsCullings.get(scene); + if (!queries) { + const cullingQuery = new LightBoundsCulling(); + cullingQuery.update(); + this.lightBoundsCullings.set(scene, cullingQuery); + queries = this.lightBoundsCullings.get(scene)!; + } + const key = computeCullingKey(sceneData, false, frustumCullingID); + const cullNum = queries.resultIndex.get(key); + if (cullNum !== undefined) { + return cullNum; + } + const lightBoundsCullingID: LightBoundsCullingID = this.numLightBoundsCulling++; + if (this.numLightBoundsCulling > this.lightBoundsCullingResults.length) { + assert(this.numLightBoundsCulling === (this.lightBoundsCullingResults.length + 1)); + this.lightBoundsCullingResults.push(new LightBoundsCullingResult()); + } + queries.resultIndex.set(key, lightBoundsCullingID); + const cullingKey = new LightBoundsCullingKey( + sceneData, + frustumCullingID, + ); + cullingKey.update( + sceneData, + frustumCullingID, + ); + queries.resultKeyIndex.set(key, cullingKey); + return lightBoundsCullingID; + } + + private getOrCreateFrustumCulling (sceneId: number): number { const sceneData: SceneData = this.renderGraph.getScene(sceneId); const scene = sceneData.scene!; - let queries = this.sceneQueries.get(scene); + let queries = this.frustumCullings.get(scene); if (!queries) { - const cullingQuery = this.cullingPools.cullingQueriesRecycle.add(); + const cullingQuery = this.cullingPools.frustumCullingsRecycle.add(); cullingQuery.update(); - this.sceneQueries.set(scene, cullingQuery); - queries = this.sceneQueries.get(scene); + this.frustumCullings.set(scene, cullingQuery); + queries = this.frustumCullings.get(scene)!; } const castShadow: boolean = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); const key = computeCullingKey(sceneData, castShadow); - const cullNum = queries!.culledResultIndex.get(key); + const cullNum = queries.resultIndex.get(key); if (cullNum !== undefined) { return cullNum; } - const sourceID = this.numCullingQueries++; - if (this.numCullingQueries > this.culledResults.length) { - assert(this.numCullingQueries === (this.culledResults.length + 1)); - this.culledResults.push([]); + const frustumCulledResultID: FrustumCullingID = this.numFrustumCulling++; + if (this.numFrustumCulling > this.frustumCullingResults.length) { + assert(this.numFrustumCulling === (this.frustumCullingResults.length + 1)); + this.frustumCullingResults.push([]); } - queries!.culledResultIndex.set(key, sourceID); - const cullingKey = this.cullingPools.cullingKeyRecycle.add(); + queries.resultIndex.set(key, frustumCulledResultID); + const cullingKey = this.cullingPools.frustumCullingKeyRecycle.add(); cullingKey.update( sceneData, castShadow, ); - queries!.cullingKeyResult.set(key, cullingKey); - return sourceID; + queries.resultKeyIndex.set(key, cullingKey); + return frustumCulledResultID; } private createRenderQueue (sceneFlags: SceneFlags, subpassOrPassLayoutID: number): number { @@ -340,6 +423,9 @@ export class SceneCulling { } assert(targetID < this.renderQueues.length); const rq = this.renderQueues[targetID]; + assert(rq.empty()); + assert(rq.sceneFlags === SceneFlags.NONE); + assert(rq.subpassOrPassLayoutID === 0xFFFFFFFF); rq.sceneFlags = sceneFlags; rq.subpassOrPassLayoutID = subpassOrPassLayoutID; return targetID; @@ -355,15 +441,16 @@ export class SceneCulling { assert(!!sceneData.scene); continue; } - const sourceID = this.getOrCreateSceneCullingQuery(v); + const frustumCulledResultID = this.getOrCreateFrustumCulling(v); + const lightBoundsCullingID = this.getOrCreateLightBoundsCulling(sceneData, frustumCulledResultID); const layoutID: number = getSubpassOrPassID(v, rg, lg); const targetID = this.createRenderQueue(sceneData.flags, layoutID); const lightType = sceneData.light.light ? sceneData.light.light.type : LightType.UNKNOWN; const renderQueueDesc = this.cullingPools.renderQueueDescRecycle.add(); - renderQueueDesc.update(sourceID, targetID, lightType); + renderQueueDesc.update(frustumCulledResultID, lightBoundsCullingID, targetID, lightType); // add render queue to query source - this.sceneQueryIndex.set(v, renderQueueDesc); + this.renderQueueIndex.set(v, renderQueueDesc); } } @@ -384,67 +471,166 @@ export class SceneCulling { return graphRenderQueue.phaseID; } - private batchCulling (pplSceneData: PipelineSceneData): void { - for (const [scene, queries] of this.sceneQueries) { + private getBuiltinShadowFrustum (pplSceneData: PipelineSceneData, camera: Camera, mainLight: DirectionalLight, level: number): Readonly { + const csmLayers = pplSceneData.csmLayers; + const csmLevel = mainLight.csmLevel; + let frustum: Readonly; + const shadows = pplSceneData.shadows; + if (shadows.type === ShadowType.Planar) { + return camera.frustum; + } + if (shadows.enabled && shadows.type === ShadowType.ShadowMap && mainLight && mainLight.node) { + // pplSceneData.updateShadowUBORange(UBOShadow.SHADOW_COLOR_OFFSET, shadows.shadowColor); + csmLayers.update(pplSceneData, camera); + } + + if (mainLight.shadowFixedArea || csmLevel === CSMLevel.LEVEL_1) { + return csmLayers.specialLayer.validFrustum; + } + return csmLayers.layers[level].validFrustum; + } + + private batchFrustumCulling (pplSceneData: PipelineSceneData): void { + for (const [scene, queries] of this.frustumCullings) { assert(!!scene); - for (const [key, sourceID] of queries.culledResultIndex) { - const cullingKey = queries.cullingKeyResult.get(key)!; + for (const [key, frustomCulledResultID] of queries.resultIndex) { + const cullingKey = queries.resultKeyIndex.get(key)!; const sceneData = cullingKey.sceneData!; assert(!!sceneData.camera); assert(sceneData.camera.scene === scene); - const camera = sceneData.camera; const light = sceneData.light.light; const level = sceneData.light.level; const castShadow = cullingKey.castShadows; - const reflectProbe = sceneData.light.probe; - assert(sourceID < this.culledResults.length); - const models = this.culledResults[sourceID]; - const isReflectProbe = bool(sceneData.flags & SceneFlags.REFLECTION_PROBE); - if (reflectProbe) { - sceneCulling(scene, reflectProbe.camera, reflectProbe.camera.frustum, castShadow, reflectProbe, isReflectProbe, models); + const probe = sceneData.light.probe; + const camera = probe ? probe.camera : sceneData.camera; + assert(frustomCulledResultID < this.frustumCullingResults.length); + const models = this.frustumCullingResults[frustomCulledResultID]; + if (probe) { + sceneCulling(scene, camera, camera.frustum, castShadow, probe, models); continue; } if (light) { switch (light.type) { case LightType.SPOT: - sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, null, isReflectProbe, models); + sceneCulling(scene, camera, (light as SpotLight).frustum, castShadow, null, models); break; case LightType.DIRECTIONAL: { - const csmLayers = pplSceneData.csmLayers; - const mainLight: DirectionalLight = light as DirectionalLight; - const csmLevel = mainLight.csmLevel; - let frustum: Readonly; - const shadows = pplSceneData.shadows; - if (shadows.type === ShadowType.Planar) { - frustum = camera.frustum; - } else { - if (shadows.enabled && shadows.type === ShadowType.ShadowMap && mainLight && mainLight.node) { - // pplSceneData.updateShadowUBORange(UBOShadow.SHADOW_COLOR_OFFSET, shadows.shadowColor); - csmLayers.update(pplSceneData, camera); - } - - if (mainLight.shadowFixedArea || csmLevel === CSMLevel.LEVEL_1) { - frustum = csmLayers.specialLayer.validFrustum; - } else { - frustum = csmLayers.layers[level].validFrustum; - } - } - sceneCulling(scene, camera, frustum, castShadow, null, isReflectProbe, models); + const frustum = this.getBuiltinShadowFrustum(pplSceneData, camera, light as DirectionalLight, level); + sceneCulling(scene, camera, frustum, castShadow, null, models); } break; default: } } else { - sceneCulling(scene, camera, camera.frustum, castShadow, null, isReflectProbe, models); + sceneCulling(scene, camera, camera.frustum, castShadow, null, models); + } + } + } + } + + private executeSphereLightCulling (light: SphereLight, frustumCullingResult: Array, lightBoundsCullingResult: Array): void { + const lightAABB = light.aabb; + for (const model of frustumCullingResult) { + assert(!!model); + const modelBounds = model.worldBounds; + if (!modelBounds || intersect.aabbWithAABB(modelBounds, lightAABB)) { + lightBoundsCullingResult.push(model); + } + } + } + + private executeSpotLightCulling (light: SpotLight, frustumCullingResult: Array, lightBoundsCullingResult: Array): void { + const lightAABB = light.aabb; + const lightFrustum: Frustum = light.frustum; + for (const model of frustumCullingResult) { + assert(!!model); + const modelBounds = model.worldBounds; + if (!modelBounds || (intersect.aabbWithAABB(lightAABB, modelBounds) && intersect.aabbFrustum(modelBounds, lightFrustum))) { + lightBoundsCullingResult.push(model); + } + } + } + + private executePointLightCulling (light: PointLight, frustumCullingResult: Array, lightBoundsCullingResult: Array): void { + const lightAABB = light.aabb; + for (const model of frustumCullingResult) { + assert(!!model); + const modelBounds = model.worldBounds; + if (!modelBounds || intersect.aabbWithAABB(lightAABB, modelBounds)) { + lightBoundsCullingResult.push(model); + } + } + } + + private executeRangedDirectionalLightCulling ( + light: RangedDirectionalLight, + frustumCullingResult: Array, + lightBoundsCullingResult: Array, + ): void { + const rangedDirLightBoundingBox = new AABB(0, 0, 0, 0.5, 0.5, 0.5); + const lightAABB = new AABB(); + rangedDirLightBoundingBox.transform(light.node!.worldMatrix, null, null, null, lightAABB); + for (const model of frustumCullingResult) { + assert(!!model); + const modelBounds = model.worldBounds; + if (!modelBounds || intersect.aabbWithAABB(lightAABB, modelBounds)) { + lightBoundsCullingResult.push(model); + } + } + } + + private batchLightBoundsCulling (): void { + for (const [scene, queries] of this.lightBoundsCullings) { + assert(!!scene); + for (const [key, cullingID] of queries.resultIndex) { + const cullingKey = queries.resultKeyIndex.get(key)!; + const sceneData = cullingKey.sceneData!; + const frustumCullingID = cullingKey.frustumCullingID; + const frustumCullingResult = this.frustumCullingResults[frustumCullingID]; + assert(!!sceneData.camera); + assert(!!sceneData.shadingLight); + assert(sceneData.camera.scene === scene); + assert(cullingID < this.frustumCullingResults.length); + const lightBoundsCullingResult = this.lightBoundsCullingResults[cullingID]; + assert(lightBoundsCullingResult.instances.length === 0); + switch (sceneData.shadingLight.type) { + case LightType.SPHERE: + { + const light = sceneData.shadingLight as SphereLight; + this.executeSphereLightCulling(light, frustumCullingResult, lightBoundsCullingResult.instances); + } + break; + case LightType.SPOT: + { + const light = sceneData.shadingLight as SpotLight; + this.executeSpotLightCulling(light, frustumCullingResult, lightBoundsCullingResult.instances); + } + break; + case LightType.POINT: + { + const light = sceneData.shadingLight as PointLight; + this.executePointLightCulling(light, frustumCullingResult, lightBoundsCullingResult.instances); + } + break; + case LightType.RANGED_DIRECTIONAL: + { + const light = sceneData.shadingLight as RangedDirectionalLight; + this.executeRangedDirectionalLightCulling(light, frustumCullingResult, lightBoundsCullingResult.instances); + } + break; + case LightType.DIRECTIONAL: + case LightType.UNKNOWN: + default: } } } } private fillRenderQueues (rg: RenderGraph, pplSceneData: PipelineSceneData): void { - for (const [sceneId, desc] of this.sceneQueryIndex) { + for (const [sceneId, desc] of this.renderQueueIndex) { assert(rg.holds(RenderGraphValue.Scene, sceneId)); - const sourceId = desc.culledSource; + const frustomCulledResultID = desc.frustumCulledResultID; + const lightBoundsCullingID = desc.lightBoundsCulledResultID; const targetId = desc.renderQueueTarget; const sceneData = rg.getScene(sceneId); const isDrawBlend: boolean = bool(sceneData.flags & SceneFlags.TRANSPARENT_OBJECT); @@ -462,8 +648,23 @@ export class SceneCulling { assert(phaseLayoutId !== this.layoutGraph.nullVertex()); // culling source - assert(sourceId < this.culledResults.length); - const sourceModels = this.culledResults[sourceId]; + assert(frustomCulledResultID < this.frustumCullingResults.length); + const sourceModels = ((): Array => { + // is culled by light bounds + if (lightBoundsCullingID !== 0xFFFFFFFF) { + if (lightBoundsCullingID < this.lightBoundsCullingResults.length) { + return this.lightBoundsCullingResults[lightBoundsCullingID].instances; + } else { + return []; + } + } + // not culled by light bounds + if (frustomCulledResultID < this.frustumCullingResults.length) { + return this.frustumCullingResults[frustomCulledResultID]; + } else { + return []; + } + })(); // queue target assert(targetId < this.renderQueues.length); @@ -490,3 +691,165 @@ export class SceneCulling { } } } + +export class LightResource { + private cpuBuffer!: Float32Array; + private programLibrary?: WebProgramLibrary; + private device: Device | null = null; + private elementSize: number = 0; + private maxNumLights: number = 16; + private binding: number = 0xFFFFFFFF; + private resized: boolean = false; + private lightBuffer?: Buffer; + private firstLightBufferView: Buffer | null = null; + private lights: Array = []; + private lightIndex: Map = new Map(); + + init (programLib: WebProgramLibrary, deviceIn: Device, maxNumLights: number): void { + assert(!this.device); + + this.device = deviceIn; + this.programLibrary = programLib; + + const instanceLayout = this.programLibrary.localLayoutData; + const attrID: number = programLib.layoutGraph.attributeIndex.get('CCForwardLight')!; + const uniformBlock = instanceLayout.uniformBlocks.get(attrID); + + this.elementSize = AlignUp( + getUniformBlockSize(uniformBlock!.members), + this.device.capabilities.uboOffsetAlignment, + ); + this.maxNumLights = maxNumLights; + this.binding = programLib.localLayoutData.bindingMap.get(attrID)!; + + const bufferSize = this.elementSize * this.maxNumLights; + + this.lightBuffer = this.device.createBuffer(new BufferInfo( + BufferUsageBit.UNIFORM | BufferUsageBit.TRANSFER_DST, + MemoryUsageBit.HOST | MemoryUsageBit.DEVICE, + bufferSize, + this.elementSize, + )); + this.firstLightBufferView = this.device.createBuffer(new BufferViewInfo( + this.lightBuffer, + 0, + this.elementSize, + )); + + this.cpuBuffer = new Float32Array(bufferSize / Float32Array.BYTES_PER_ELEMENT); + this.lights = new Array(this.maxNumLights); + this.lightIndex = new Map(); + + assert(!!(this.elementSize && this.maxNumLights)); + this.resized = true; + } + + buildLights (sceneCulling: SceneCulling, bHDR: boolean, shadowInfo: Shadows | null): void { + // Build light buffer + for (const [scene, lightBoundsCullings] of sceneCulling.lightBoundsCullings) { + for (const [key, lightBoundsCullingID] of lightBoundsCullings.resultIndex) { + const lightBoundsCulling = lightBoundsCullings.resultKeyIndex.get(key)!; + const sceneData = lightBoundsCulling.sceneData!; + let exposure: number = 1.0; + if (sceneData.camera) { + exposure = sceneData.camera.exposure; + } else if (sceneData.light.probe && sceneData.light.probe.camera) { + exposure = sceneData.light.probe.camera.exposure; + } else { + throw new Error('Unexpected situation: No camera or probe found.'); + } + const lightByteOffset: number = this.addLight( + sceneData.shadingLight!, + bHDR, + exposure, + shadowInfo, + ); + + // Save light byte offset for each light bounds culling + const result: LightBoundsCullingResult = sceneCulling.lightBoundsCullingResults[lightBoundsCullingID]; + result.lightByteOffset = lightByteOffset; + } + } + + // Assign light byte offset to each queue + for (const [sceneID, desc] of sceneCulling.renderQueueIndex) { + if (desc.lightBoundsCulledResultID === 0xFFFFFFFF) { + continue; + } + const lightByteOffset: number = sceneCulling.lightBoundsCullingResults[desc.lightBoundsCulledResultID].lightByteOffset; + + sceneCulling.renderQueues[desc.renderQueueTarget].lightByteOffset = lightByteOffset; + } + } + + tryUpdateRenderSceneLocalDescriptorSet (sceneCulling: SceneCulling): void { + if (!this.resized) { + return; + } + + for (const [scene, culling] of sceneCulling.frustumCullings) { + for (const model of scene.models) { + if (!model) { + throw new Error('Unexpected null model.'); + } + for (const submodel of model.subModels) { + const set = submodel.descriptorSet; + set.bindBuffer(this.binding, this.firstLightBufferView!); + set.update(); + } + } + } + this.resized = false; + } + + clear (): void { + this.cpuBuffer.fill(0); + this.lights.length = 0; + this.lightIndex.clear(); + } + + addLight (light: Light, bHDR: boolean, exposure: number, shadowInfo: Shadows | null): number { + // Already added + const existingLightID = this.lightIndex.get(light); + if (existingLightID !== undefined) { + return existingLightID; + } + + // Resize buffer if needed + if (this.lights.length === this.maxNumLights) { + this.resized = true; + this.maxNumLights *= 2; + const bufferSize = this.elementSize * this.maxNumLights; + this.lightBuffer!.resize(bufferSize); + this.firstLightBufferView = this.device!.createBuffer(new BufferViewInfo( + this.lightBuffer, + 0, + this.elementSize, + )); + this.cpuBuffer = new Float32Array(bufferSize / Float32Array.BYTES_PER_ELEMENT); + this.lights = new Array(this.maxNumLights); + this.lightIndex = new Map(); + } + + assert(this.lights.length < this.maxNumLights); + + // Add light + const lightID = this.lights.length; + this.lights[lightID] = light; + this.lightIndex.set(light, lightID); + + // Update buffer + const offset = this.elementSize * lightID; + SetLightUBO(light, bHDR, exposure, shadowInfo, this.cpuBuffer, offset, this.elementSize); + + return lightID * this.elementSize; + } + + buildLightBuffer (cmdBuffer: CommandBuffer): void { + cmdBuffer.updateBuffer( + this.lightBuffer!, + this.cpuBuffer, + (this.lights.length * this.elementSize) / Float32Array.BYTES_PER_ELEMENT, + ); + } +} diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 52b3ecccb7a..48de876bcb0 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -1,6 +1,7 @@ -import { RecyclePool, cclegacy } from '../../core'; +import { RecyclePool, assert, cclegacy } from '../../core'; import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; -import { IMacroPatch } from '../../render-scene'; +import { IMacroPatch, Pass } from '../../render-scene'; + import { LightType, Model, SubModel } from '../../render-scene/scene'; import { SetIndex } from '../define'; import { InstancedBuffer } from '../instanced-buffer'; @@ -68,6 +69,11 @@ function getPassIndexFromLayout (subModel: SubModel, phaseLayoutId: number): num export class ProbeHelperQueue { probeMap: Array = new Array(); defaultId: number = getLayoutId('default', 'default'); + + clear (): void { + this.probeMap.length = 0; + } + removeMacro (): void { for (const subModel of this.probeMap) { let patches: IMacroPatch[] = []; @@ -119,6 +125,14 @@ export class ProbeHelperQueue { export class RenderDrawQueue { instances: Array = new Array(); + empty (): boolean { + return this.instances.length === 0; + } + + clear (): void { + this.instances.length = 0; + } + add (model: Model, depth: number, subModelIdx: number, passIdx: number): void { const subModel = model.subModels[subModelIdx]; const pass = subModel.passes[passIdx]; @@ -169,6 +183,9 @@ export class RenderDrawQueue { device: Device, renderPass: RenderPass, cmdBuffer: CommandBuffer, + ds: DescriptorSet | null = null, + offset = 0, + dynamicOffsets: number[] | null = null, ): void { for (const instance of this.instances) { const subModel = instance.subModel!; @@ -181,7 +198,17 @@ export class RenderDrawQueue { cmdBuffer.bindPipelineState(pso); cmdBuffer.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); - cmdBuffer.bindDescriptorSet(SetIndex.LOCAL, subModel.descriptorSet); + if (ds) { + cmdBuffer.bindDescriptorSet(SetIndex.GLOBAL, ds, [offset]); + } + if (dynamicOffsets) { + cmdBuffer.bindDescriptorSet(SetIndex.LOCAL, subModel.descriptorSet, dynamicOffsets); + } else { + cmdBuffer.bindDescriptorSet( + SetIndex.LOCAL, + subModel.descriptorSet, + ); + } cmdBuffer.bindInputAssembler(inputAssembler); cmdBuffer.draw(inputAssembler); } @@ -189,19 +216,60 @@ export class RenderDrawQueue { } export class RenderInstancingQueue { - batches: Set = new Set(); + passInstances: Map = new Map(); + instanceBuffers: Set = new Set(); sortedBatches: Array = new Array(); - add (instancedBuffer: InstancedBuffer): void { - this.batches.add(instancedBuffer); + empty (): boolean { + return this.passInstances.size === 0; + } + + add (pass: Pass, subModel: SubModel, passID: number): void { + const iter = this.passInstances.get(pass); + if (iter === undefined) { + const instanceBufferID = this.passInstances.size; + if (instanceBufferID >= this.instanceBuffers.size) { + assert(instanceBufferID === this.instanceBuffers.size); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.instanceBuffers.add(new InstancedBuffer(new Pass(cclegacy.director.root))); + } + this.passInstances.set(pass, instanceBufferID); + + assert(instanceBufferID < this.instanceBuffers.size); + const instanceBuffer = this.instanceBuffers[instanceBufferID]; + instanceBuffer.setPass(pass); + const instances = instanceBuffer.getInstances(); + for (const item of instances) { + assert(item.drawInfo.instanceCount === 0); + } + } + + const instancedBuffer = this.instanceBuffers[this.passInstances.get(pass)!]; + instancedBuffer.merge(subModel, passID); + } + + clear (): void { + this.sortedBatches.length = 0; + this.passInstances.clear(); + const it = this.instanceBuffers.values(); let res = it.next(); + while (!res.done) { + res.value.clear(); + res = it.next(); + } + this.instanceBuffers.clear(); } sort (): void { - this.sortedBatches = Array.from(this.batches); + this.sortedBatches.length = this.passInstances.size; + let index = 0; + for (const [pass, bufferID] of this.passInstances.entries()) { + this.sortedBatches[index++] = this.instanceBuffers[bufferID]; + } } uploadBuffers (cmdBuffer: CommandBuffer): void { - for (const instanceBuffer of this.batches) { + for (const [pass, bufferID] of this.passInstances.entries()) { + const instanceBuffer = this.instanceBuffers[bufferID]; if (instanceBuffer.hasPendingModels) { instanceBuffer.uploadBuffers(cmdBuffer); } @@ -259,25 +327,30 @@ export class RenderInstancingQueue { } export class RenderQueueDesc { - culledSource: number; + frustumCulledResultID: number; + lightBoundsCulledResultID: number; renderQueueTarget: number; lightType: LightType; constructor ( - culledSourceIn = 0xFFFFFFFF, + frustumCulledResultID = 0xFFFFFFFF, + lightBoundsCulledResultID = 0xFFFFFFFF, renderQueueTargetIn = 0xFFFFFFFF, lightTypeIn: LightType = LightType.UNKNOWN, ) { - this.culledSource = culledSourceIn; + this.frustumCulledResultID = frustumCulledResultID; + this.lightBoundsCulledResultID = lightBoundsCulledResultID; this.renderQueueTarget = renderQueueTargetIn; this.lightType = lightTypeIn; } update ( culledSourceIn = 0xFFFFFFFF, + lightBoundsCulledResultID = 0xFFFFFFFF, renderQueueTargetIn = 0xFFFFFFFF, lightTypeIn: LightType = LightType.UNKNOWN, ): void { - this.culledSource = culledSourceIn; + this.frustumCulledResultID = culledSourceIn; + this.lightBoundsCulledResultID = lightBoundsCulledResultID; this.renderQueueTarget = renderQueueTargetIn; this.lightType = lightTypeIn; } @@ -290,8 +363,8 @@ export class RenderQueue { opaqueInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); transparentInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); sceneFlags: SceneFlags = SceneFlags.NONE; - subpassOrPassLayoutID = 0xffffffff; - + subpassOrPassLayoutID = 0xFFFFFFFF; + lightByteOffset = 0xFFFFFFFF; sort (): void { this.opaqueQueue.sortOpaqueOrCutout(); this.transparentQueue.sortTransparent(); @@ -299,33 +372,29 @@ export class RenderQueue { this.transparentInstancingQueue.sort(); } - private _clearInstances (instances: Set): void { - const it = instances.values(); let res = it.next(); - while (!res.done) { - res.value.clear(); - res = it.next(); - } - instances.clear(); - } - update (): void { - this.probeQueue.probeMap.length = 0; - this.opaqueQueue.instances.length = 0; - this.transparentQueue.instances.length = 0; - this._clearInstances(this.opaqueInstancingQueue.batches); - this.opaqueInstancingQueue.sortedBatches.length = 0; - this._clearInstances(this.transparentInstancingQueue.batches); - this.transparentInstancingQueue.sortedBatches.length = 0; + this.probeQueue.clear(); + this.opaqueQueue.clear(); + this.transparentQueue.clear(); + this.opaqueInstancingQueue.clear(); + this.transparentInstancingQueue.clear(); this.sceneFlags = SceneFlags.NONE; this.subpassOrPassLayoutID = 0xFFFFFFFF; } empty (): boolean { - return this.opaqueQueue.instances.length === 0 - && this.transparentQueue.instances.length === 0 - && this.opaqueInstancingQueue.batches.size === 0 - && this.opaqueInstancingQueue.sortedBatches.length === 0 - && this.transparentInstancingQueue.batches.size === 0 - && this.transparentInstancingQueue.sortedBatches.length === 0; + return this.opaqueQueue.empty() + && this.transparentQueue.empty() + && this.opaqueInstancingQueue.empty() + && this.transparentInstancingQueue.empty(); + } + + recordCommands (cmdBuffer: CommandBuffer, renderPass: RenderPass): void { + const offset = this.lightByteOffset === 0xFFFFFFFF ? 0 : this.lightByteOffset / Float32Array.BYTES_PER_ELEMENT; + this.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, [offset]); + this.opaqueInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, [offset]); + + this.transparentInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, [offset]); + this.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, [offset]); } } diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 9c26269b844..a4b1739fad3 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -59,6 +59,7 @@ import { Scene } from '../../scene-graph'; import { Director } from '../../game'; import { ReflectionProbeManager } from '../../3d'; import { legacyCC } from '../../core/global-exports'; +import { WebProgramLibrary } from './web-program-library'; const _uboVec = new Vec4(); const _uboVec3 = new Vec3(); @@ -1198,7 +1199,14 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild } addSceneOfCamera (camera: Camera, light: LightInfo, sceneFlags = SceneFlags.NONE, name = 'Camera'): void { - const sceneData = renderGraphPool.createSceneData(camera.scene, camera, sceneFlags, CullingFlags.NONE, light.light); + const lightTarget = light.light; + const sceneData = renderGraphPool.createSceneData( + camera.scene, + camera, + sceneFlags, + lightTarget ? CullingFlags.CAMERA_FRUSTUM | CullingFlags.LIGHT_BOUNDS : CullingFlags.CAMERA_FRUSTUM, + lightTarget, + ); this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, name, '', renderGraphPool.createRenderData(), false, this._vertID); const layoutName = this.getParentLayout(); const scene: Scene = cclegacy.director.getScene(); @@ -1210,7 +1218,7 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild layoutName, ); if (sceneFlags & SceneFlags.SHADOW_CASTER) { - setShadowUBOLightView(this, camera, light.light!, light.level, layoutName); + setShadowUBOLightView(this, camera, lightTarget!, light.level, layoutName); } else { setShadowUBOView(this, camera, layoutName); } @@ -1218,10 +1226,13 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild initGlobalDescBinding(this._data, layoutName); } addScene (camera: Camera, sceneFlags = SceneFlags.NONE, light: Light | undefined = undefined): SceneBuilder { - const sceneData = renderGraphPool.createSceneData(camera.scene, camera, sceneFlags); - if (light) { - sceneData.light.light = light; - } + const sceneData = renderGraphPool.createSceneData( + camera.scene, + camera, + sceneFlags, + light ? CullingFlags.CAMERA_FRUSTUM | CullingFlags.LIGHT_BOUNDS : CullingFlags.CAMERA_FRUSTUM, + light, + ); const renderData = renderGraphPool.createRenderData(); const sceneId = this._renderGraph.addVertex(RenderGraphValue.Scene, sceneData, 'Scene', '', renderData, false, this._vertID); if (!(sceneFlags & SceneFlags.NON_BUILTIN)) { @@ -2134,7 +2145,6 @@ export class WebPipeline implements BasicPipeline { if (this.usesDeferredPipeline) { this.setMacroInt('CC_PIPELINE_TYPE', 1); } - this._forward = new ForwardPipelineBuilder(); this._deferred = new DeferredPipelineBuilder(); this.builder = new CustomPipelineBuilder(); diff --git a/cocos/rendering/custom/web-program-library.ts b/cocos/rendering/custom/web-program-library.ts index ba0e5e7ee51..802ca51b189 100644 --- a/cocos/rendering/custom/web-program-library.ts +++ b/cocos/rendering/custom/web-program-library.ts @@ -24,7 +24,7 @@ /* eslint-disable max-len */ import { EffectAsset } from '../../asset/assets'; -import { Attribute, DescriptorSetLayout, DescriptorType, DESCRIPTOR_BUFFER_TYPE, DESCRIPTOR_SAMPLER_TYPE, Device, MemoryAccessBit, PipelineLayout, PipelineLayoutInfo, Shader, ShaderInfo, ShaderStage, ShaderStageFlagBit, Type, Uniform, UniformBlock, UniformInputAttachment, UniformSampler, UniformSamplerTexture, UniformStorageBuffer, UniformStorageImage, UniformTexture, deviceManager } from '../../gfx'; +import { Attribute, DescriptorSetLayout, DescriptorType, DESCRIPTOR_BUFFER_TYPE, DESCRIPTOR_SAMPLER_TYPE, Device, MemoryAccessBit, PipelineLayout, PipelineLayoutInfo, Shader, ShaderInfo, ShaderStage, ShaderStageFlagBit, Type, Uniform, UniformBlock, UniformInputAttachment, UniformSampler, UniformSamplerTexture, UniformStorageBuffer, UniformStorageImage, UniformTexture, deviceManager, PipelineState, DescriptorSetLayoutInfo, DescriptorSetInfo } from '../../gfx'; import { genHandles, getActiveAttributes, getCombinationDefines, getShaderInstanceName, getSize, getVariantKey, populateMacros, prepareDefines } from '../../render-scene/core/program-utils'; import { getDeviceShaderVersion, MacroRecord } from '../../render-scene'; import { IProgramInfo } from '../../render-scene/core/program-lib'; @@ -32,15 +32,15 @@ import { DescriptorBlockData, DescriptorData, DescriptorSetData, DescriptorSetLa import { ProgramLibrary, ProgramProxy } from './private'; import { DescriptorTypeOrder, UpdateFrequency } from './types'; import { ProgramGroup, ProgramInfo } from './web-types'; -import { getCustomPassID, getCustomPhaseID, getOrCreateDescriptorSetLayout, getEmptyDescriptorSetLayout, getEmptyPipelineLayout, initializeDescriptorSetLayoutInfo, makeDescriptorSetLayoutData, getDescriptorSetLayout, getOrCreateDescriptorID, getDescriptorTypeOrder, getProgramID, getDescriptorNameID, getDescriptorName, INVALID_ID, ENABLE_SUBPASS, getCustomSubpassID } from './layout-graph-utils'; -import { assert } from '../../core/platform/debug'; -import { IDescriptorSetLayoutInfo, localDescriptorSetLayout } from '../define'; +import { getCustomPassID, getCustomPhaseID, getOrCreateDescriptorSetLayout, getEmptyDescriptorSetLayout, getEmptyPipelineLayout, initializeDescriptorSetLayoutInfo, makeDescriptorSetLayoutData, getDescriptorSetLayout, getOrCreateDescriptorID, getDescriptorTypeOrder, getProgramID, getDescriptorNameID, getDescriptorName, INVALID_ID, ENABLE_SUBPASS, getCustomSubpassID, generateConstantMacros, populatePipelineLayoutInfo } from './layout-graph-utils'; +import { assert, error } from '../../core/platform/debug'; +import { IDescriptorSetLayoutInfo, UBOSkinning, localDescriptorSetLayout } from '../define'; import { PipelineRuntime } from './pipeline'; const _setIndex = [2, 1, 3, 0]; // make IProgramInfo from IShaderInfo -function makeProgramInfo (effectName: string, shader: EffectAsset.IShaderInfo): IProgramInfo { +export function makeProgramInfo (effectName: string, shader: EffectAsset.IShaderInfo): IProgramInfo { const programInfo = { ...shader } as IProgramInfo; programInfo.effectName = effectName; @@ -86,7 +86,7 @@ function findBinding (shaderInfo: ShaderInfo, name: string): { set: number, bind } } // eslint-disable-next-line no-console - throw console.error('binding not found in shaderInfo!'); + throw error('binding not found in shaderInfo!'); } function overwriteShaderSourceBinding (shaderInfo: ShaderInfo, source: string): string { @@ -130,7 +130,7 @@ function overwriteShaderProgramBinding (shaderInfo: ShaderInfo, programInfo: IPr } // overwrite IProgramInfo using gfx.ShaderInfo -function overwriteProgramBlockInfo (shaderInfo: ShaderInfo, programInfo: IProgramInfo): void { +export function overwriteProgramBlockInfo (shaderInfo: ShaderInfo, programInfo: IProgramInfo): void { overwriteShaderProgramBinding(shaderInfo, programInfo); const set = _setIndex[UpdateFrequency.PER_BATCH]; for (const block of programInfo.blocks) { @@ -146,7 +146,7 @@ function overwriteProgramBlockInfo (shaderInfo: ShaderInfo, programInfo: IProgra } } if (!found) { - console.error(`Block ${block.name} not found in shader ${shaderInfo.name}`); + error(`Block ${block.name} not found in shader ${shaderInfo.name}`); } } } @@ -262,7 +262,7 @@ function populateMergedShaderInfo ( for (const block of descriptorBlock.descriptors) { const uniformBlock = layout.uniformBlocks.get(block.descriptorID); if (uniformBlock === undefined) { - console.error(`Failed to find uniform block ${block.descriptorID} in layout`); + error(`Failed to find uniform block ${block.descriptorID} in layout`); continue; } blockSizes.push(getSize(uniformBlock.members)); @@ -278,7 +278,7 @@ function populateMergedShaderInfo ( ++binding; } if (binding !== descriptorBlock.offset + descriptorBlock.capacity) { - console.error(`Uniform buffer binding mismatch for set ${set}`); + error(`Uniform buffer binding mismatch for set ${set}`); } break; case DescriptorTypeOrder.DYNAMIC_UNIFORM_BUFFER: @@ -533,7 +533,7 @@ function calculateFlattenedBinding ( } // make gfx.ShaderInfo -function makeShaderInfo ( +export function makeShaderInfo ( lg: LayoutGraphData, passLayouts: PipelineLayoutData, phaseLayouts: PipelineLayoutData, @@ -642,14 +642,23 @@ function makeShaderInfo ( return [shaderInfo, blockSizes]; } -class WebProgramProxy implements ProgramProxy { - constructor (shader: Shader) { +export function getGLSLSource (info: IProgramInfo, version: string): { vert: string, frag: string, compute?: string } { + if (version === 'glsl1') return info.glsl1; + if (version === 'glsl3') return info.glsl3; + if (version === 'glsl4') return info.glsl4; + return { vert: '', frag: '' }; +} + +export class WebProgramProxy implements ProgramProxy { + constructor (shader: Shader, pipelineStateIn: PipelineState | null = null) { this.shader = shader; + this.pipelineState = pipelineStateIn; } get name (): string { return this.shader.name; } readonly shader: Shader; + pipelineState: PipelineState | null = null; } // find name and type from local descriptor set info @@ -667,12 +676,12 @@ function getDescriptorNameAndType (source: IDescriptorSetLayoutInfo, binding: nu return [v.name, type]; } } - console.error('descriptor not found'); + error('descriptor not found'); return ['', Type.UNKNOWN]; } // make DescriptorSetLayoutData from local descriptor set info -function makeLocalDescriptorSetLayoutData ( +export function makeLocalDescriptorSetLayoutData ( lg: LayoutGraphData, source: IDescriptorSetLayoutInfo, ): DescriptorSetLayoutData { @@ -687,7 +696,7 @@ function makeLocalDescriptorSetLayoutData ( data.descriptorBlocks.push(block); const binding = data.bindingMap.get(nameID); if (binding !== undefined) { - console.error(`duplicate descriptor name '${name}'`); + error(`duplicate descriptor name '${name}'`); } data.bindingMap.set(nameID, b.binding); const v = source.layouts[name]; @@ -699,7 +708,7 @@ function makeLocalDescriptorSetLayoutData ( } // make descriptor sets for ShaderProgramData (PerBatch, PerInstance) -function buildProgramData ( +export function buildProgramData ( programName: string, srcShaderInfo: EffectAsset.IShaderInfo, lg: LayoutGraphData, @@ -729,7 +738,7 @@ function buildProgramData ( setData.descriptorSetLayoutInfo, ); if (localDescriptorSetLayout.bindings.length !== setData.descriptorSetLayoutInfo.bindings.length) { - console.error('local descriptor set layout inconsistent'); + error('local descriptor set layout inconsistent'); } else { for (let k = 0; k !== localDescriptorSetLayout.bindings.length; ++k) { const b = localDescriptorSetLayout.bindings[k]; @@ -738,7 +747,7 @@ function buildProgramData ( || b.descriptorType !== b2.descriptorType || b.count !== b2.count || b.stageFlags !== b2.stageFlags) { - console.error('local descriptor set layout inconsistent'); + error('local descriptor set layout inconsistent'); } } } @@ -763,7 +772,7 @@ function buildProgramData ( } // get or create PerProgram gfx.DescriptorSetLayout -function getOrCreateProgramDescriptorSetLayout ( +export function getOrCreateProgramDescriptorSetLayout ( device: Device, lg: LayoutGraphData, phaseID: number, @@ -790,7 +799,7 @@ function getOrCreateProgramDescriptorSetLayout ( } // get PerProgram gfx.DescriptorSetLayout -function getProgramDescriptorSetLayout ( +export function getProgramDescriptorSetLayout ( device: Device, lg: LayoutGraphData, phaseID: number, @@ -817,7 +826,7 @@ function getProgramDescriptorSetLayout ( } // find shader program in LayoutGraphData -function getEffectShader ( +export function getEffectShader ( lg: LayoutGraphData, effect: EffectAsset, pass: EffectAsset.IPassInfo, @@ -825,20 +834,20 @@ function getEffectShader ( const programName = pass.program; const passID = getCustomPassID(lg, pass.pass); if (passID === INVALID_ID) { - console.error(`Invalid render pass, program: ${programName}`); + error(`Invalid render pass, program: ${programName}`); return [INVALID_ID, INVALID_ID, INVALID_ID, null, INVALID_ID]; } const enableSubpass = pass.subpass && pass.subpass !== '' && ENABLE_SUBPASS; const subpassID = enableSubpass ? getCustomSubpassID(lg, passID, pass.subpass!) : INVALID_ID; if (enableSubpass && subpassID === INVALID_ID) { - console.error(`Invalid render subpass, program: ${programName}`); + error(`Invalid render subpass, program: ${programName}`); return [INVALID_ID, INVALID_ID, INVALID_ID, null, INVALID_ID]; } const phaseID = getCustomPhaseID(lg, subpassID === INVALID_ID ? passID : subpassID, pass.phase); if (phaseID === INVALID_ID) { - console.error(`Invalid render phase, program: ${programName}`); + error(`Invalid render phase, program: ${programName}`); return [INVALID_ID, INVALID_ID, INVALID_ID, null, INVALID_ID]; } let srcShaderInfo: EffectAsset.IShaderInfo | null = null; @@ -855,10 +864,10 @@ function getEffectShader ( } // valid IShaderInfo is compatible -function validateShaderInfo (srcShaderInfo: EffectAsset.IShaderInfo): number { +export function validateShaderInfo (srcShaderInfo: EffectAsset.IShaderInfo): number { // source shader info if (srcShaderInfo.descriptors === undefined) { - console.error(`No descriptors in shader: ${srcShaderInfo.name}, please reimport ALL effects`); + error(`No descriptors in shader: ${srcShaderInfo.name}, please reimport ALL effects`); return 1; } return 0; @@ -873,6 +882,75 @@ export class WebProgramLibrary implements ProgramLibrary { } } } + init (deviceIn: Device): void { + if (this.device === deviceIn) { + return; + } + this.device = deviceIn; + this.emptyDescriptorSetLayout = this.device.createDescriptorSetLayout(new DescriptorSetLayoutInfo()); + this.emptyPipelineLayout = this.device.createPipelineLayout(new PipelineLayoutInfo()); + + // update ubo + // tips: for compatibility with old version, when maxVertexUniformVectors is 128, maxJoints = 30 + let maxJoints: number = (this.device.capabilities.maxVertexUniformVectors - 38) / 3; + maxJoints = maxJoints < 256 ? maxJoints : 256; + UBOSkinning.initLayout(maxJoints); + + // init layout graph + const lg = this.layoutGraph; + for (const v of lg.vertices()) { + const layout: PipelineLayoutData = lg.get('Layout').get(v) as PipelineLayoutData; + for (const [update, set] of layout.descriptorSets) { + initializeDescriptorSetLayoutInfo(set.descriptorSetLayoutData, set.descriptorSetLayoutInfo); + set.descriptorSetLayout = this.device.createDescriptorSetLayout(set.descriptorSetLayoutInfo); + assert(!!set.descriptorSetLayout); + set.descriptorSet = this.device.createDescriptorSet(new DescriptorSetInfo(set.descriptorSetLayout)); + assert(!!set.descriptorSet); + } + } + + for (const v of lg.vertices()) { + if (!lg.holds(LayoutGraphDataValue.RenderPhase, v)) { + continue; + } + const phaseID = v; + const subpassOrPassID = lg.getParent(phaseID); + const passLayout = lg.getLayout(subpassOrPassID); + const phaseLayout = lg.getLayout(phaseID); + const info = new PipelineLayoutInfo(); + populatePipelineLayoutInfo(passLayout, UpdateFrequency.PER_PASS, info); + populatePipelineLayoutInfo(phaseLayout, UpdateFrequency.PER_PHASE, info); + populatePipelineLayoutInfo(phaseLayout, UpdateFrequency.PER_BATCH, info); + populatePipelineLayoutInfo(phaseLayout, UpdateFrequency.PER_INSTANCE, info); + const phase = lg.getRenderPhase(phaseID); + phase.pipelineLayout = this.device.createPipelineLayout(info); + } + + // init local descriptor set + { + const localSetLayout = localDescriptorSetLayout; + this.localLayoutData = makeLocalDescriptorSetLayoutData(lg, localSetLayout); + const info = new DescriptorSetLayoutInfo(); + initializeDescriptorSetLayoutInfo(this.localLayoutData, info); + this.localDescriptorSetLayout = this.device.createDescriptorSetLayout(info); + assert(!!this.localDescriptorSetLayout); + + let numUniformBuffers = 0; + for (const block of this.localLayoutData.descriptorBlocks) { + if (block.type !== DescriptorTypeOrder.UNIFORM_BUFFER + && block.type !== DescriptorTypeOrder.DYNAMIC_UNIFORM_BUFFER) { + continue; + } + for (const d of block.descriptors) { + numUniformBuffers += d.count; + } + } + assert(numUniformBuffers === 7); // 7 is currently max uniform binding + } + + // generate constant macros string + generateConstantMacros(this.device, this.layoutGraph.constantMacros); + } // add effect to database addEffect (effect: EffectAsset): void { const lg = this.layoutGraph; @@ -881,7 +959,7 @@ export class WebProgramLibrary implements ProgramLibrary { const programName = pass.program; const [passID, subpassID, phaseID, srcShaderInfo] = getEffectShader(lg, effect, pass); if (srcShaderInfo === null || validateShaderInfo(srcShaderInfo)) { - console.error(`program: ${programName} not found`); + error(`program: ${programName} not found`); continue; } assert(passID !== INVALID_ID && phaseID !== INVALID_ID); @@ -942,7 +1020,7 @@ export class WebProgramLibrary implements ProgramLibrary { const programName = pass.program; const [passID, subpassID, phaseID, srcShaderInfo, shaderID] = getEffectShader(lg, effect, pass); if (srcShaderInfo === null || validateShaderInfo(srcShaderInfo)) { - console.error(`program: ${programName} not valid`); + error(`program: ${programName} not valid`); continue; } assert(passID !== INVALID_ID && phaseID !== INVALID_ID && shaderID !== INVALID_ID); @@ -978,13 +1056,13 @@ export class WebProgramLibrary implements ProgramLibrary { // get phase const group = this.phases.get(phaseID); if (group === undefined) { - console.error(`Invalid render phase, program: ${programName}`); + error(`Invalid render phase, program: ${programName}`); return ''; } // get info const info = group.programInfos.get(programName); if (info === undefined) { - console.error(`Invalid program, program: ${programName}`); + error(`Invalid program, program: ${programName}`); return ''; } return getVariantKey(info.programInfo, defines); @@ -996,13 +1074,13 @@ export class WebProgramLibrary implements ProgramLibrary { // get phase const group = this.phases.get(phaseID); if (group === undefined) { - console.error(`Invalid render phase, program: ${name}`); + error(`Invalid render phase, program: ${name}`); return null; } // get info const info = group.programInfos.get(name); if (info === undefined) { - console.error(`Invalid program, program: ${name}`); + error(`Invalid program, program: ${name}`); return null; } const programInfo = info.programInfo; @@ -1027,7 +1105,7 @@ export class WebProgramLibrary implements ProgramLibrary { if (deviceShaderVersion) { src = programInfo[deviceShaderVersion]; } else { - console.error('Invalid GFX API!'); + error('Invalid GFX API!'); } // prepare shader info @@ -1088,12 +1166,12 @@ export class WebProgramLibrary implements ProgramLibrary { assert(phaseID !== INVALID_ID); const group = this.phases.get(phaseID); if (!group) { - console.error(`Invalid render phase, program: ${programName}`); + error(`Invalid render phase, program: ${programName}`); return []; } const info = group.programInfos.get(programName); if (!info) { - console.error(`Invalid program, program: ${programName}`); + error(`Invalid program, program: ${programName}`); return []; } return info.blockSizes; @@ -1103,12 +1181,12 @@ export class WebProgramLibrary implements ProgramLibrary { assert(phaseID !== INVALID_ID); const group = this.phases.get(phaseID); if (!group) { - console.error(`Invalid render phase, program: ${programName}`); + error(`Invalid render phase, program: ${programName}`); return {}; } const info = group.programInfos.get(programName); if (!info) { - console.error(`Invalid program, program: ${programName}`); + error(`Invalid program, program: ${programName}`); return {}; } return info.handleMap; @@ -1169,7 +1247,12 @@ export class WebProgramLibrary implements ProgramLibrary { } readonly layoutGraph: LayoutGraphData; readonly phases: Map = new Map(); - mergeHighFrequency = false; - fixedLocal = true; - pipeline: PipelineRuntime | null = null; + public mergeHighFrequency: boolean = false; + public fixedLocal: boolean = true; + public localLayoutData: DescriptorSetLayoutData = new DescriptorSetLayoutData(); + public localDescriptorSetLayout: DescriptorSetLayout | null = null; + public emptyDescriptorSetLayout: DescriptorSetLayout | null = null; + public emptyPipelineLayout: PipelineLayout | null = null; + public pipeline: PipelineRuntime | null = null; + public device: Device | null = null; } diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index 9b4cf87efd0..eac17607070 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -70,13 +70,15 @@ export class ForwardPass extends BasePass { } } } - pass.addQueue(QueueHint.RENDER_OPAQUE) - .addSceneOfCamera( - camera, - new LightInfo(), - SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT + const forwardQueue = pass.addQueue(QueueHint.RENDER_OPAQUE); + forwardQueue.addSceneOfCamera( + camera, + new LightInfo(), + SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, - ); + ); + const forwardAddQueue = pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'forward-add'); + passContext.addSceneLights(forwardAddQueue, camera); const shadowInfo = ppl.pipelineSceneData.shadows; if (camera.scene?.mainLight && shadowInfo.enabled && shadowInfo.type === ShadowType.Planar) { pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'planar-shadow') diff --git a/cocos/rendering/post-process/utils/pass-context.ts b/cocos/rendering/post-process/utils/pass-context.ts index 0921cf0b717..e6c2a755e1b 100644 --- a/cocos/rendering/post-process/utils/pass-context.ts +++ b/cocos/rendering/post-process/utils/pass-context.ts @@ -1,14 +1,17 @@ import { EDITOR } from 'internal:constants'; -import { QueueHint, ResourceResidency, SceneFlags } from '../../custom/types'; +import { LightInfo, QueueHint, ResourceResidency, SceneFlags } from '../../custom/types'; import { ClearFlagBit, Color, Format, LoadOp, Rect, StoreOp, Viewport } from '../../../gfx'; -import { Pipeline, RenderPassBuilder } from '../../custom/pipeline'; +import { Pipeline, RenderPassBuilder, RenderQueueBuilder } from '../../custom/pipeline'; import { Camera, SKYBOX_FLAG } from '../../../render-scene/scene'; import { Material } from '../../../asset/assets'; import { PostProcess } from '../components'; import { getRenderArea } from '../../custom/define'; -import { Vec4 } from '../../../core'; +import { Vec4, geometry } from '../../../core'; +const sphere = geometry.Sphere.create(0, 0, 0, 1); +const boundingBox = new geometry.AABB(); +const rangedDirLightBoundingBox = new geometry.AABB(0.0, 0.0, 0.0, 0.5, 0.5, 0.5); export class PassContext { clearFlag: ClearFlagBit = ClearFlagBit.COLOR; clearColor = new Color(); @@ -81,6 +84,50 @@ export class PassContext { return this; } + addSceneLights (queue: RenderQueueBuilder, camera: Camera, flags: SceneFlags = SceneFlags.BLEND): void { + const scene = camera.scene!; + for (let i = 0; i < scene.spotLights.length; i++) { + const light = scene.spotLights[i]; + if (light.baked) { + continue; + } + geometry.Sphere.set(sphere, light.position.x, light.position.y, light.position.z, light.range); + if (geometry.intersect.sphereFrustum(sphere, camera.frustum)) { + queue.addSceneOfCamera(camera, new LightInfo(light), flags); + } + } + // sphere lights + for (let i = 0; i < scene.sphereLights.length; i++) { + const light = scene.sphereLights[i]; + if (light.baked) { + continue; + } + geometry.Sphere.set(sphere, light.position.x, light.position.y, light.position.z, light.range); + if (geometry.intersect.sphereFrustum(sphere, camera.frustum)) { + queue.addSceneOfCamera(camera, new LightInfo(light), flags); + } + } + // point lights + for (let i = 0; i < scene.pointLights.length; i++) { + const light = scene.pointLights[i]; + if (light.baked) { + continue; + } + geometry.Sphere.set(sphere, light.position.x, light.position.y, light.position.z, light.range); + if (geometry.intersect.sphereFrustum(sphere, camera.frustum)) { + queue.addSceneOfCamera(camera, new LightInfo(light), flags); + } + } + // ranged dir lights + for (let i = 0; i < scene.rangedDirLights.length; i++) { + const light = scene.rangedDirLights[i]; + geometry.AABB.transform(boundingBox, rangedDirLightBoundingBox, light.node!.getWorldMatrix()); + if (geometry.intersect.aabbFrustum(boundingBox, camera.frustum)) { + queue.addSceneOfCamera(camera, new LightInfo(light), flags); + } + } + } + updateViewPort (): void { const camera = this.camera; if (!camera) { diff --git a/cocos/rendering/render-additive-light-queue.ts b/cocos/rendering/render-additive-light-queue.ts index 0b6534f7ccc..f24a66eb08a 100644 --- a/cocos/rendering/render-additive-light-queue.ts +++ b/cocos/rendering/render-additive-light-queue.ts @@ -183,7 +183,7 @@ export class RenderAdditiveLightQueue { } } - private _bindForwardAddLight(validPunctualLights: Light[], passLayout = 'default'): void { + private _bindForwardAddLight (validPunctualLights: Light[], passLayout = 'default'): void { const renderObjects = this._pipeline.pipelineSceneData.renderObjects; for (let i = 0; i < renderObjects.length; i++) { const ro = renderObjects[i]; From 2a934795fd36e71646021814775615139e3f5034 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Mon, 23 Oct 2023 18:09:44 +0800 Subject: [PATCH 78/82] Fix multiple light sources (#180) --- cocos/rendering/custom/executor.ts | 1 + cocos/rendering/custom/scene-culling.ts | 2 +- cocos/rendering/custom/web-pipeline-types.ts | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 5e450300d28..98de6f47889 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1308,6 +1308,7 @@ class GraphScene { this.scene.light.light = scene.light.light; this.scene.flags = scene.flags; this.scene.camera = scene.camera; + this.scene.shadingLight = scene.shadingLight; return; } this.scene = null; diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 5ab7d58739e..943706fe4de 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -783,7 +783,7 @@ export class LightResource { } tryUpdateRenderSceneLocalDescriptorSet (sceneCulling: SceneCulling): void { - if (!this.resized) { + if (!this.resized || !sceneCulling.lightBoundsCullings.size) { return; } diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 48de876bcb0..030f573814c 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -390,11 +390,11 @@ export class RenderQueue { } recordCommands (cmdBuffer: CommandBuffer, renderPass: RenderPass): void { - const offset = this.lightByteOffset === 0xFFFFFFFF ? 0 : this.lightByteOffset / Float32Array.BYTES_PER_ELEMENT; - this.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, [offset]); - this.opaqueInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, [offset]); + const offsets = this.lightByteOffset === 0xFFFFFFFF ? null : [this.lightByteOffset / Float32Array.BYTES_PER_ELEMENT]; + this.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, offsets); + this.opaqueInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, offsets); - this.transparentInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, [offset]); - this.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, [offset]); + this.transparentInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, offsets); + this.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, offsets); } } From a2784da46b50e2594525a60726b0c2f2cb84be5b Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Mon, 30 Oct 2023 09:16:11 +0800 Subject: [PATCH 79/82] [Add] lightbounds pool (#181) --- cocos/rendering/custom/scene-culling.ts | 34 +++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 943706fe4de..3cbfbde66b5 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -20,6 +20,9 @@ const vec3Pool = new ObjectPool(() => new Vec3()); class CullingPools { frustumCullingKeyRecycle = new RecyclePool(() => new FrustumCullingKey(), 8); frustumCullingsRecycle = new RecyclePool(() => new FrustumCulling(), 8); + lightBoundsCullingRecycle = new RecyclePool(() => new LightBoundsCulling(), 8); + lightBoundsCullingResultRecycle = new RecyclePool(() => new LightBoundsCullingResult(), 8); + lightBoundsCullingKeyRecycle = new RecyclePool(() => new LightBoundsCullingKey(), 8); renderQueueRecycle = new RecyclePool(() => new RenderQueue(), 8); renderQueueDescRecycle = new RecyclePool(() => new RenderQueueDesc(), 8); } @@ -124,6 +127,11 @@ class LightBoundsCulling { class LightBoundsCullingResult { instances: Array = new Array(); lightByteOffset: number = 0xFFFFFFFF; + update (): LightBoundsCullingResult { + this.instances.length = 0; + this.lightByteOffset = 0xFFFFFFFF; + return this; + } } type FrustumCullingID = number; @@ -298,7 +306,8 @@ function addRenderObject ( } } } - +const rangedDirLightBoundingBox = new AABB(0, 0, 0, 0.5, 0.5, 0.5); +const lightAABB = new AABB(); export class SceneCulling { frustumCullings: Map = new Map(); frustumCullingResults: Array> = new Array>(); @@ -315,10 +324,14 @@ export class SceneCulling { layoutGraph; renderGraph; resetPool (): void { - this.cullingPools.frustumCullingKeyRecycle.reset(); - this.cullingPools.frustumCullingsRecycle.reset(); - this.cullingPools.renderQueueRecycle.reset(); - this.cullingPools.renderQueueDescRecycle.reset(); + const cullingPools = this.cullingPools; + cullingPools.frustumCullingKeyRecycle.reset(); + cullingPools.frustumCullingsRecycle.reset(); + cullingPools.lightBoundsCullingRecycle.reset(); + cullingPools.lightBoundsCullingResultRecycle.reset(); + cullingPools.lightBoundsCullingKeyRecycle.reset(); + cullingPools.renderQueueRecycle.reset(); + cullingPools.renderQueueDescRecycle.reset(); instancePool.reset(); } clear (): void { @@ -354,7 +367,7 @@ export class SceneCulling { let queries = this.lightBoundsCullings.get(scene); if (!queries) { - const cullingQuery = new LightBoundsCulling(); + const cullingQuery = this.cullingPools.lightBoundsCullingRecycle.add(); cullingQuery.update(); this.lightBoundsCullings.set(scene, cullingQuery); queries = this.lightBoundsCullings.get(scene)!; @@ -367,13 +380,10 @@ export class SceneCulling { const lightBoundsCullingID: LightBoundsCullingID = this.numLightBoundsCulling++; if (this.numLightBoundsCulling > this.lightBoundsCullingResults.length) { assert(this.numLightBoundsCulling === (this.lightBoundsCullingResults.length + 1)); - this.lightBoundsCullingResults.push(new LightBoundsCullingResult()); + this.lightBoundsCullingResults.push(this.cullingPools.lightBoundsCullingResultRecycle.add().update()); } queries.resultIndex.set(key, lightBoundsCullingID); - const cullingKey = new LightBoundsCullingKey( - sceneData, - frustumCullingID, - ); + const cullingKey = this.cullingPools.lightBoundsCullingKeyRecycle.add(); cullingKey.update( sceneData, frustumCullingID, @@ -567,8 +577,6 @@ export class SceneCulling { frustumCullingResult: Array, lightBoundsCullingResult: Array, ): void { - const rangedDirLightBoundingBox = new AABB(0, 0, 0, 0.5, 0.5, 0.5); - const lightAABB = new AABB(); rangedDirLightBoundingBox.transform(light.node!.worldMatrix, null, null, null, lightAABB); for (const model of frustumCullingResult) { assert(!!model); From 2021d78600fc211ea602ce7e745d383f16540bb2 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Tue, 31 Oct 2023 11:40:39 +0800 Subject: [PATCH 80/82] Solve the problem that only one light source is effective in the case of multiple light sources (#182) --- cocos/rendering/custom/scene-culling.ts | 2 +- cocos/rendering/custom/web-pipeline-types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts index 3cbfbde66b5..c2b74a07516 100644 --- a/cocos/rendering/custom/scene-culling.ts +++ b/cocos/rendering/custom/scene-culling.ts @@ -847,7 +847,7 @@ export class LightResource { this.lightIndex.set(light, lightID); // Update buffer - const offset = this.elementSize * lightID; + const offset = this.elementSize / Float32Array.BYTES_PER_ELEMENT * lightID; SetLightUBO(light, bHDR, exposure, shadowInfo, this.cpuBuffer, offset, this.elementSize); return lightID * this.elementSize; diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 030f573814c..2ab78817f55 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -390,7 +390,7 @@ export class RenderQueue { } recordCommands (cmdBuffer: CommandBuffer, renderPass: RenderPass): void { - const offsets = this.lightByteOffset === 0xFFFFFFFF ? null : [this.lightByteOffset / Float32Array.BYTES_PER_ELEMENT]; + const offsets = this.lightByteOffset === 0xFFFFFFFF ? null : [this.lightByteOffset]; this.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, renderPass, cmdBuffer, null, 0, offsets); this.opaqueInstancingQueue.recordCommandBuffer(renderPass, cmdBuffer, null, 0, offsets); From 8f632f2f91756b01baebf658afb5654717c2656c Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Thu, 2 Nov 2023 11:00:12 +0800 Subject: [PATCH 81/82] Update instancing (#183) --- cocos/rendering/custom/web-pipeline-types.ts | 27 ++++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts index 2ab78817f55..28024fe8e46 100644 --- a/cocos/rendering/custom/web-pipeline-types.ts +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -217,7 +217,7 @@ export class RenderDrawQueue { export class RenderInstancingQueue { passInstances: Map = new Map(); - instanceBuffers: Set = new Set(); + instanceBuffers: Array = new Array(); sortedBatches: Array = new Array(); empty (): boolean { @@ -228,19 +228,19 @@ export class RenderInstancingQueue { const iter = this.passInstances.get(pass); if (iter === undefined) { const instanceBufferID = this.passInstances.size; - if (instanceBufferID >= this.instanceBuffers.size) { - assert(instanceBufferID === this.instanceBuffers.size); + if (instanceBufferID >= this.instanceBuffers.length) { + assert(instanceBufferID === this.instanceBuffers.length); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this.instanceBuffers.add(new InstancedBuffer(new Pass(cclegacy.director.root))); + this.instanceBuffers.push(new InstancedBuffer(new Pass(cclegacy.director.root))); } this.passInstances.set(pass, instanceBufferID); - assert(instanceBufferID < this.instanceBuffers.size); + assert(instanceBufferID < this.instanceBuffers.length); const instanceBuffer = this.instanceBuffers[instanceBufferID]; - instanceBuffer.setPass(pass); - const instances = instanceBuffer.getInstances(); + instanceBuffer.pass = pass; + const instances = instanceBuffer.instances; for (const item of instances) { - assert(item.drawInfo.instanceCount === 0); + assert(item.count === 0); } } @@ -251,12 +251,11 @@ export class RenderInstancingQueue { clear (): void { this.sortedBatches.length = 0; this.passInstances.clear(); - const it = this.instanceBuffers.values(); let res = it.next(); - while (!res.done) { - res.value.clear(); - res = it.next(); - } - this.instanceBuffers.clear(); + const instanceBuffers = this.instanceBuffers; + instanceBuffers.forEach((instance) => { + instance.clear(); + }); + this.instanceBuffers.length = 0; } sort (): void { From 9475df97f2c356647c3e2356693b06f875de6d16 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Mon, 6 Nov 2023 18:25:30 +0800 Subject: [PATCH 82/82] Fix shadowmap flickering problem with multiple light sources (#184) * Fix shadowmap flickering problem with multiple light sources * update --- cocos/rendering/custom/define.ts | 7 ++- cocos/rendering/custom/executor.ts | 4 +- cocos/rendering/custom/web-pipeline.ts | 50 ++++++++++++++++++- .../post-process/passes/forward-pass.ts | 4 +- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index 7226335f21f..0f03b0472ac 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -682,11 +682,10 @@ export function buildShadowPass ( ); } const queue = shadowPass.addQueue(QueueHint.RENDER_OPAQUE, 'shadow-caster'); - queue.addSceneOfCamera( + queue.addScene( camera, - new LightInfo(light, level), - SceneFlags.SHADOW_CASTER | SceneFlags.OPAQUE_OBJECT | SceneFlags.TRANSPARENT_OBJECT, - ); + SceneFlags.SHADOW_CASTER | SceneFlags.OPAQUE_OBJECT | SceneFlags.MASK, + ).useLightFrustum(light, light.type !== LightType.DIRECTIONAL ? 0 : level); queue.setViewport(new Viewport(area.x, area.y, area.width, area.height)); } diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index d4e18fda7c2..5e6f45aa2d5 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -1526,7 +1526,9 @@ class DeviceSceneTask extends WebSceneTask { const queueId = this._currentQueue.queueId; const queueRenderData = context.renderGraph.getData(queueId)!; this._updateGlobal(queueRenderData); - + const sceneId = this.graphScene.sceneID; + const sceneRenderData = context.renderGraph.getData(sceneId)!; + if (sceneRenderData) this._updateGlobal(sceneRenderData); const layoutName = context.renderGraph.getLayout(rasterId); const descSetData = getDescriptorSetDataFromLayout(layoutName); mergeSrcToTargetDesc(descSetData!.descriptorSet, context.descriptorSet, true); diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index bc3709cf8ce..0a76a1f7506 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -688,6 +688,8 @@ function setShadowUBOLightView ( Mat4.invert(_matView, spotLight.node!.getWorldMatrix()); } if (setter.hasUniform(matViewOffset)) setter.offsetMat4(_matView, matViewOffset); + let matShadowInvProj!: Mat4; + let matShadowProj!: Mat4; if (setter.hasUniform(matViewProOffset)) { Mat4.perspective( _mulMatView, @@ -700,6 +702,8 @@ function setShadowUBOLightView ( cap.clipSpaceSignY, 0, ); + matShadowProj = _mulMatView.clone(); + matShadowInvProj = _mulMatView.clone().invert(); Mat4.multiply(_matView, _mulMatView, _matView); setter.offsetMat4(_matView, matViewProOffset); } @@ -718,6 +722,47 @@ function setShadowUBOLightView ( _uboVec.set(LightType.SPOT, packing, spotLight.shadowNormalBias, 0.0); setter.offsetVec4(_uboVec, uniformOffset); } + uniformOffset = setter.getUniformOffset('cc_shadowProjDepthInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(matShadowProj.m10, matShadowProj.m14, matShadowProj.m11, matShadowProj.m15); + setter.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = setter.getUniformOffset('cc_shadowInvProjDepthInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(matShadowInvProj.m10, matShadowInvProj.m14, matShadowInvProj.m11, matShadowInvProj.m15); + setter.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = setter.getUniformOffset('cc_shadowProjInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(matShadowProj.m00, matShadowProj.m05, 1.0 / matShadowProj.m00, 1.0 / matShadowProj.m05); + setter.offsetVec4(_uboVec, uniformOffset); + } + } + break; + } + case LightType.SPHERE: { + uniformOffset = setter.getUniformOffset('cc_shadowWHPBInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(shadowInfo.size.x, shadowInfo.size.y, 1.0, 0.0); + setter.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = setter.getUniformOffset('cc_shadowLPNNInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(LightType.SPHERE, packing, 0.0, 0.0); + setter.offsetVec4(_uboVec, uniformOffset); + } + break; + } + case LightType.POINT: { + uniformOffset = setter.getUniformOffset('cc_shadowWHPBInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(shadowInfo.size.x, shadowInfo.size.y, 1.0, 0.0); + setter.offsetVec4(_uboVec, uniformOffset); + } + uniformOffset = setter.getUniformOffset('cc_shadowLPNNInfo', Type.FLOAT4); + if (setter.hasUniform(uniformOffset)) { + _uboVec.set(LightType.POINT, packing, 0.0, 0.0); + setter.offsetVec4(_uboVec, uniformOffset); } break; } @@ -1226,7 +1271,7 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild camera.scene || (scene ? scene.renderScene : null), layoutName, ); - if (sceneFlags & SceneFlags.SHADOW_CASTER) { + if (sceneFlags & SceneFlags.SHADOW_CASTER || (lightTarget && lightTarget.type !== LightType.DIRECTIONAL)) { setShadowUBOLightView(this, camera, lightTarget!, light.level, layoutName); } else { setShadowUBOView(this, camera, layoutName); @@ -1253,7 +1298,8 @@ export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuild camera.scene, layoutName, ); - setShadowUBOView(this, camera, layoutName); + if (light && light.type !== LightType.DIRECTIONAL) setShadowUBOLightView(this, camera, light, 0, layoutName); + else if (!(sceneFlags & SceneFlags.SHADOW_CASTER)) setShadowUBOView(this, camera, layoutName); setTextureUBOView(this, camera, this._pipeline); initGlobalDescBinding(this._data, layoutName); } diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index eac17607070..c16d0b493c7 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -75,7 +75,7 @@ export class ForwardPass extends BasePass { camera, new LightInfo(), SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT - | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, + | SceneFlags.GEOMETRY, ); const forwardAddQueue = pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'forward-add'); passContext.addSceneLights(forwardAddQueue, camera); @@ -86,7 +86,7 @@ export class ForwardPass extends BasePass { camera, new LightInfo(camera.scene?.mainLight), SceneFlags.TRANSPARENT_OBJECT | SceneFlags.SHADOW_CASTER - | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, + | SceneFlags.GEOMETRY, ); } passContext.forwardPass = this;