From 14ccfecf04623437355a48ad8e81085d9dffaf00 Mon Sep 17 00:00:00 2001 From: zxx43 Date: Fri, 4 Mar 2022 11:14:20 +0800 Subject: [PATCH] add layouts --- .../custom/web-descriptor-hierarchy.ts | 276 +++++++++++++++++- 1 file changed, 274 insertions(+), 2 deletions(-) diff --git a/cocos/core/pipeline/custom/web-descriptor-hierarchy.ts b/cocos/core/pipeline/custom/web-descriptor-hierarchy.ts index 9482de33588..1c4000de6fa 100644 --- a/cocos/core/pipeline/custom/web-descriptor-hierarchy.ts +++ b/cocos/core/pipeline/custom/web-descriptor-hierarchy.ts @@ -25,18 +25,290 @@ import { EffectAsset } from '../../assets'; import { DescriptorHierarchy } from './pipeline'; -import { LayoutGraph } from './layout-graph'; +import { Descriptor, DescriptorBlock, DescriptorBlockIndex, DescriptorDB, DescriptorIndex, LayoutGraph, LayoutGraphValue, RenderPhase, UniformBlockDB } from './layout-graph'; +import { ShaderStageFlagBit, Type, Uniform } from '../../gfx'; +import { ParameterType, UpdateFrequency } from './types'; +import { JOINT_UNIFORM_CAPACITY, UBOForwardLight, UBOLocalBatched, UBOMorph } from '../define'; export class WebDescriptorHierarchy extends DescriptorHierarchy { constructor () { super(); this._layoutGraph = new LayoutGraph(); } + + private getLayoutBlock(freq: UpdateFrequency, paraType: ParameterType, descType: DescriptorIndex, vis: ShaderStageFlagBit, descriptorDB: DescriptorDB): DescriptorBlock { + const blockIndex: DescriptorBlockIndex = new DescriptorBlockIndex(freq, paraType, descType, vis); + const key = JSON.stringify(blockIndex); + if (descriptorDB.blocks.get(key) === undefined) { + const uniformBlock: DescriptorBlock = new DescriptorBlock(); + descriptorDB.blocks.set(key, uniformBlock); + } + return descriptorDB.blocks.get(key) as DescriptorBlock; + } + + private getUniformBlock(blockName: string, targetBlock: DescriptorBlock): UniformBlockDB { + if (targetBlock.uniformBlocks.get(blockName) === undefined) { + let uniformDB: UniformBlockDB = new UniformBlockDB(); + targetBlock.uniformBlocks.set(blockName, uniformDB); + } + return targetBlock.uniformBlocks.get(blockName) as UniformBlockDB; + } + + private setUniform(uniformDB: UniformBlockDB, name: string, type: Type, count: number) { + const uniform: Uniform = new Uniform(name, type, count); + uniformDB.values.set(uniform.name, uniform); + } + + private setDescriptor(targetBlock: DescriptorBlock, name: string, type: Type) { + const descriptor: Descriptor = new Descriptor(type); + targetBlock.descriptors.set(name, descriptor); + } + public addEffect (asset: EffectAsset): void { const sz = asset.shaders.length; + + let hasCCGlobal = false; + let hasCCCamera = false; + let hasCCShadow = false; + let hasShadowmap = false; + let hasEnv = false; + let hasDiffuse = false; + let hasSpot = false; + for (let i = 0; i !== sz; ++i) { - const shader = asset.shaders[i]; + const shader: EffectAsset.IShaderInfo = asset.shaders[i]; + + const queueDB: DescriptorDB = new DescriptorDB(); + + for (let k in shader.blocks) { + const blockInfo: EffectAsset.IBlockInfo = shader.blocks[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_INSTANCE, + ParameterType.TABLE, DescriptorIndex.UNIFORM_BLOCK, blockInfo.stageFlags, queueDB); + let uniformDB: UniformBlockDB = this.getUniformBlock(blockInfo.name, targetBlock); + for (let kk in blockInfo.members) { + const uniform: Uniform = blockInfo.members[kk]; + uniformDB.values.set(uniform.name, uniform); + } + } + + for (let k in shader.buffers) { + const bufferInfo: EffectAsset.IBufferInfo = shader.buffers[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_QUEUE, + ParameterType.TABLE, DescriptorIndex.STORAGE_BUFFER, bufferInfo.stageFlags, queueDB); + this.setDescriptor(targetBlock, bufferInfo.name, Type.UNKNOWN); + } + + for (let k in shader.images) { + const imageInfo: EffectAsset.IImageInfo = shader.images[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_QUEUE, + ParameterType.TABLE, DescriptorIndex.STORAGE_TEXTURE, imageInfo.stageFlags, queueDB); + this.setDescriptor(targetBlock, imageInfo.name, imageInfo.type); + } + + for (let k in shader.samplerTextures) { + const samplerTexInfo: EffectAsset.ISamplerTextureInfo = shader.samplerTextures[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_BATCH, + ParameterType.TABLE, DescriptorIndex.SAMPLER_TEXTURE, samplerTexInfo.stageFlags, queueDB); + this.setDescriptor(targetBlock, samplerTexInfo.name, samplerTexInfo.type); + } + + for (let k in shader.samplers) { + const samplerInfo: EffectAsset.ISamplerInfo = shader.samplers[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_QUEUE, + ParameterType.TABLE, DescriptorIndex.SAMPLER, samplerInfo.stageFlags, queueDB); + this.setDescriptor(targetBlock, samplerInfo.name, Type.SAMPLER); + } + + for (let k in shader.textures) { + const texInfo: EffectAsset.ITextureInfo = shader.textures[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_QUEUE, + ParameterType.TABLE, DescriptorIndex.TEXTURE, texInfo.stageFlags, queueDB); + this.setDescriptor(targetBlock, texInfo.name, texInfo.type); + } + + for (let k in shader.subpassInputs) { + const subpassInfo: EffectAsset.IInputAttachmentInfo = shader.subpassInputs[k]; + let targetBlock: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_QUEUE, + ParameterType.TABLE, DescriptorIndex.SUBPASS_INPUT, subpassInfo.stageFlags, queueDB); + this.setDescriptor(targetBlock, subpassInfo.name, Type.SUBPASS_INPUT); + } + + // Add queue layout from define.ts + const localUniformTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_INSTANCE, + ParameterType.TABLE, DescriptorIndex.UNIFORM_BLOCK, ShaderStageFlagBit.VERTEX, queueDB); + const localLightTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_QUEUE, + ParameterType.TABLE, DescriptorIndex.UNIFORM_BLOCK, ShaderStageFlagBit.FRAGMENT, queueDB); + const localModelTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_INSTANCE, + ParameterType.TABLE, DescriptorIndex.UNIFORM_BLOCK, ShaderStageFlagBit.VERTEX | ShaderStageFlagBit.COMPUTE, queueDB); + const localSamplerVertTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_BATCH, + ParameterType.TABLE, DescriptorIndex.SAMPLER_TEXTURE, ShaderStageFlagBit.VERTEX, queueDB); + const localSamplerFragTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_BATCH, + ParameterType.TABLE, DescriptorIndex.SAMPLER_TEXTURE, ShaderStageFlagBit.FRAGMENT, queueDB); + const localSamplerCompTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_BATCH, + ParameterType.TABLE, DescriptorIndex.SAMPLER_TEXTURE, ShaderStageFlagBit.COMPUTE, queueDB); + + for (let k = 0; k < shader.builtins.locals.blocks.length; ++k) { + const blockName: string = shader.builtins.locals.blocks[k].name; + if (blockName === 'CCMorph') { + let morphDB: UniformBlockDB = this.getUniformBlock('CCMorph', localUniformTarget); + this.setUniform(morphDB, 'cc_displacementWeights', Type.FLOAT4, UBOMorph.MAX_MORPH_TARGET_COUNT / 4); + this.setUniform(morphDB, 'cc_displacementTextureInfo', Type.FLOAT4, 1); + } else if (blockName === 'CCSkinningTexture') { + let skinningTexDB: UniformBlockDB = this.getUniformBlock('CCSkinningTexture', localUniformTarget); + this.setUniform(skinningTexDB, 'cc_jointTextureInfo', Type.FLOAT4, 1); + } else if (blockName === 'CCSkinningAnimation') { + let skinningAnimDB: UniformBlockDB = this.getUniformBlock('CCSkinningAnimation', localUniformTarget); + this.setUniform(skinningAnimDB, 'cc_jointAnimInfo', Type.FLOAT4, 1); + } else if (blockName === 'CCSkinning') { + let skinningDB: UniformBlockDB = this.getUniformBlock('CCSkinning', localUniformTarget); + this.setUniform(skinningDB, 'cc_joints', Type.FLOAT4, JOINT_UNIFORM_CAPACITY * 3); + } else if (blockName === 'CCUILocal') { + let uiDB: UniformBlockDB = this.getUniformBlock('CCUILocal', localUniformTarget); + this.setUniform(uiDB, 'cc_local_data', Type.FLOAT4, 1); + } else if (blockName === 'CCForwardLight') { + let lightDB: UniformBlockDB = this.getUniformBlock('CCForwardLight', localLightTarget); + this.setUniform(lightDB, 'cc_lightPos', Type.FLOAT4, UBOForwardLight.LIGHTS_PER_PASS); + this.setUniform(lightDB, 'cc_lightColor', Type.FLOAT4, UBOForwardLight.LIGHTS_PER_PASS); + this.setUniform(lightDB, 'cc_lightSizeRangeAngle', Type.FLOAT4, UBOForwardLight.LIGHTS_PER_PASS); + this.setUniform(lightDB, 'cc_lightDir', Type.FLOAT4, UBOForwardLight.LIGHTS_PER_PASS); + } else if (blockName === 'CCLocal') { + let localDB: UniformBlockDB = this.getUniformBlock('CCLocal', localModelTarget); + this.setUniform(localDB, 'cc_matWorld', Type.MAT4, 1); + this.setUniform(localDB, 'cc_matWorldIT', Type.MAT4, 1); + this.setUniform(localDB, 'cc_lightingMapUVParam', Type.FLOAT4, 1); + } else if (blockName === 'CCLocalBatched') { + let batchDB: UniformBlockDB = this.getUniformBlock('CCLocalBatched', localModelTarget); + this.setUniform(batchDB, 'cc_matWorlds', Type.MAT4, UBOLocalBatched.BATCHING_COUNT); + } else if (blockName === 'CCWorldBound') { + let boundDB: UniformBlockDB = this.getUniformBlock('CCWorldBound', localModelTarget); + this.setUniform(boundDB, 'cc_worldBoundCenter', Type.FLOAT4, 1); + this.setUniform(boundDB, 'cc_worldBoundHalfExtents', Type.FLOAT4, 1); + } + } + + for (let k = 0; k < shader.builtins.locals.samplerTextures.length; ++k) { + const samplerName: string = shader.builtins.locals.samplerTextures[k].name; + if (samplerName === 'cc_jointTexture') { + this.setDescriptor(localSamplerVertTarget, 'cc_jointTexture', Type.SAMPLER2D); + } else if (samplerName === 'cc_PositionDisplacements') { + this.setDescriptor(localSamplerVertTarget, 'cc_PositionDisplacements', Type.SAMPLER2D); + } else if (samplerName === 'cc_NormalDisplacements') { + this.setDescriptor(localSamplerVertTarget, 'cc_NormalDisplacements', Type.SAMPLER2D); + } else if (samplerName === 'cc_TangentDisplacements') { + this.setDescriptor(localSamplerVertTarget, 'cc_TangentDisplacements', Type.SAMPLER2D); + } else if (samplerName === 'cc_lightingMap') { + this.setDescriptor(localSamplerFragTarget, 'cc_lightingMap', Type.SAMPLER2D); + } else if (samplerName === 'cc_spriteTexture') { + this.setDescriptor(localSamplerFragTarget, 'cc_spriteTexture', Type.SAMPLER2D); + } else if (samplerName === 'cc_reflectionTexture') { + this.setDescriptor(localSamplerFragTarget, 'cc_reflectionTexture', Type.SAMPLER2D); + } + } + + for (let k = 0; k < shader.builtins.locals.images.length; ++k) { + const imgName: string = shader.builtins.locals.images[k].name; + if (imgName === 'cc_reflectionStorage') { + this.setDescriptor(localSamplerCompTarget, 'cc_reflectionStorage', Type.IMAGE2D); + } + } + + const phase: RenderPhase = new RenderPhase(); + phase.shaders.add(shader.name); + this._layoutGraph.addVertex(LayoutGraphValue.RenderPhase, phase, shader.name, queueDB); + + for (let k = 0; k < shader.builtins.globals.blocks.length; ++k) { + const blockName = shader.builtins.globals.blocks[k].name; + if (blockName === 'CCGlobal') { + hasCCGlobal = true; + } else if (blockName === 'CCCamera') { + hasCCCamera = true; + } else if (blockName === 'CCShadow') { + hasCCShadow = true; + } + } + + for (let k = 0; k < shader.builtins.globals.samplerTextures.length; ++k) { + const samplerName = shader.builtins.globals.samplerTextures[k].name; + if (samplerName === 'cc_shadowMap') { + hasShadowmap = true; + } else if (samplerName === 'cc_environment') { + hasEnv = true; + } else if (samplerName === 'cc_diffuseMap') { + hasDiffuse = true; + } else if (samplerName === 'cc_spotLightingMap') { + hasSpot = true; + } + } + } + + const passDB: DescriptorDB = new DescriptorDB(); + // Add pass layout from define.ts + let globalUniformTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_PASS, + ParameterType.TABLE, DescriptorIndex.UNIFORM_BLOCK, ShaderStageFlagBit.ALL, passDB); + let globalSamplerTexTarget: DescriptorBlock = this.getLayoutBlock(UpdateFrequency.PER_PASS, + ParameterType.TABLE, DescriptorIndex.SAMPLER_TEXTURE, ShaderStageFlagBit.FRAGMENT, passDB); + + if (hasCCGlobal) { + let globalDB: UniformBlockDB = this.getUniformBlock('CCGlobal', globalUniformTarget); + this.setUniform(globalDB, 'cc_time', Type.FLOAT4, 1); + this.setUniform(globalDB, 'cc_screenSize', Type.FLOAT4, 1); + this.setUniform(globalDB, 'cc_nativeSize', Type.FLOAT4, 1); + } + + if (hasCCCamera) { + let cameraDB: UniformBlockDB = this.getUniformBlock('CCCamera', globalUniformTarget); + this.setUniform(cameraDB, 'cc_matView', Type.MAT4, 1); + this.setUniform(cameraDB, 'cc_matViewInv', Type.MAT4, 1); + this.setUniform(cameraDB, 'cc_matProj', Type.MAT4, 1); + this.setUniform(cameraDB, 'cc_matProjInv', Type.MAT4, 1); + this.setUniform(cameraDB, 'cc_matViewProj', Type.MAT4, 1); + this.setUniform(cameraDB, 'cc_matViewProjInv', Type.MAT4, 1); + this.setUniform(cameraDB, 'cc_cameraPos', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_screenScale', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_exposure', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_mainLitDir', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_mainLitColor', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_ambientSky', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_ambientGround', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_fogColor', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_fogBase', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_fogAdd', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_nearFar', Type.FLOAT4, 1); + this.setUniform(cameraDB, 'cc_viewPort', Type.FLOAT4, 1); } + + if (hasCCShadow) { + let shadowDB: UniformBlockDB = this.getUniformBlock('CCShadow', globalUniformTarget); + this.setUniform(shadowDB, 'cc_matLightPlaneProj', Type.MAT4, 1); + this.setUniform(shadowDB, 'cc_matLightView', Type.MAT4, 1); + this.setUniform(shadowDB, 'cc_matLightViewProj', Type.MAT4, 1); + this.setUniform(shadowDB, 'cc_shadowInvProjDepthInfo', Type.FLOAT4, 1); + this.setUniform(shadowDB, 'cc_shadowProjDepthInfo', Type.FLOAT4, 1); + this.setUniform(shadowDB, 'cc_shadowProjInfo', Type.FLOAT4, 1); + this.setUniform(shadowDB, 'cc_shadowNFLSInfo', Type.FLOAT4, 1); + this.setUniform(shadowDB, 'cc_shadowWHPBInfo', Type.FLOAT4, 1); + this.setUniform(shadowDB, 'cc_shadowLPNNInfo', Type.FLOAT4, 1); + this.setUniform(shadowDB, 'cc_shadowColor', Type.FLOAT4, 1); + } + + if (hasShadowmap) { + this.setDescriptor(globalSamplerTexTarget, 'cc_shadowMap', Type.SAMPLER2D); + } + if (hasEnv) { + this.setDescriptor(globalSamplerTexTarget, 'cc_environment', Type.SAMPLER_CUBE); + } + if (hasDiffuse) { + this.setDescriptor(globalSamplerTexTarget, 'cc_diffuseMap', Type.SAMPLER_CUBE); + } + if (hasSpot) { + this.setDescriptor(globalSamplerTexTarget, 'cc_spotLightingMap', Type.SAMPLER2D); + } + + this._layoutGraph.addVertex(LayoutGraphValue.RenderStage, LayoutGraphValue.RenderStage, asset.name, passDB); } private _layoutGraph: LayoutGraph; + + public get layoutGraph () { + return this._layoutGraph; + } }