diff --git a/cocos/asset/assets/rendering-sub-mesh.ts b/cocos/asset/assets/rendering-sub-mesh.ts index a648dc6a3ea..439539bde8c 100644 --- a/cocos/asset/assets/rendering-sub-mesh.ts +++ b/cocos/asset/assets/rendering-sub-mesh.ts @@ -135,8 +135,11 @@ export class RenderingSubMesh { * @param indirectBuffer @en indirect buffer. @zh 间接缓冲区。 */ constructor ( - vertexBuffers: Buffer[], attributes: Attribute[], primitiveMode: PrimitiveMode, - indexBuffer: Buffer | null = null, indirectBuffer: Buffer | null = null, + vertexBuffers: Buffer[], + attributes: Attribute[], + primitiveMode: PrimitiveMode, + indexBuffer: Buffer | null = null, + indirectBuffer: Buffer | null = null, isOwnerOfIndexBuffer = true, ) { this._attributes = attributes; @@ -144,7 +147,7 @@ export class RenderingSubMesh { this._indexBuffer = indexBuffer; this._indirectBuffer = indirectBuffer; this._primitiveMode = primitiveMode; - this._iaInfo = new InputAssemblerInfo(attributes, vertexBuffers, indexBuffer, indirectBuffer); + this._iaInfo = new InputAssemblerInfo(attributes, vertexBuffers, indexBuffer); this._isOwnerOfIndexBuffer = isOwnerOfIndexBuffer; } @@ -197,7 +200,7 @@ export class RenderingSubMesh { const indices = mesh.readIndices(index) as Uint16Array; const max = new Vec3(); const min = new Vec3(); - const pAttri = this.attributes.find((element): boolean => element.name === AttributeName.ATTR_POSITION); + const pAttri = this.attributes.find((element): boolean => element.name === AttributeName.ATTR_POSITION as string); if (pAttri) { const conut = FormatInfos[pAttri.format].count; if (conut === 2) { @@ -307,14 +310,14 @@ export class RenderingSubMesh { } let jointFormat: Format; let jointOffset: number; - const { device } = cclegacy.director.root; + const device = cclegacy.director.root.device as Device; for (let i = 0; i < prim.vertexBundelIndices.length; i++) { const bundle = struct.vertexBundles[prim.vertexBundelIndices[i]]; jointOffset = 0; jointFormat = Format.UNKNOWN; for (let j = 0; j < bundle.attributes.length; j++) { const attr = bundle.attributes[j]; - if (attr.name === AttributeName.ATTR_JOINTS) { + if (attr.name === AttributeName.ATTR_JOINTS as string) { jointFormat = attr.format; break; } @@ -324,8 +327,15 @@ export class RenderingSubMesh { const data = new Uint8Array(this.mesh.data.buffer, bundle.view.offset, bundle.view.length); const dataView = new DataView(data.slice().buffer); const idxMap = struct.jointMaps[prim.jointMapIndex]; - mapBuffer(dataView, (cur): number => idxMap.indexOf(cur), jointFormat, jointOffset, - bundle.view.length, bundle.view.stride, dataView); + mapBuffer( + dataView, + (cur): number => idxMap.indexOf(cur), + jointFormat, + jointOffset, + bundle.view.length, + bundle.view.stride, + dataView, + ); const buffer = device.createBuffer(new BufferInfo( BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, MemoryUsageBit.DEVICE, diff --git a/cocos/gfx/base/define.ts b/cocos/gfx/base/define.ts index 53eeb4062cb..ed23330b928 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. + MUTABLE_STORAGE = 0x10, // Texture is mutable or not, default is immutable(only for webgl2) + LAZILY_ALLOCATED = 0x20, // Try lazily allocated mode. } export enum FormatFeatureBit { @@ -1502,14 +1503,12 @@ export class InputAssemblerInfo { public attributes: Attribute[] = [], public vertexBuffers: Buffer[] = [], public indexBuffer: Buffer | null = null, - public indirectBuffer: Buffer | null = null, ) {} public copy (info: Readonly): InputAssemblerInfo { deepCopy(this.attributes, info.attributes, Attribute); this.vertexBuffers = info.vertexBuffers.slice(); this.indexBuffer = info.indexBuffer; - this.indirectBuffer = info.indirectBuffer; return this; } } diff --git a/cocos/gfx/base/input-assembler.ts b/cocos/gfx/base/input-assembler.ts index 84312b9aa3b..ca088ee2a4f 100644 --- a/cocos/gfx/base/input-assembler.ts +++ b/cocos/gfx/base/input-assembler.ts @@ -55,14 +55,6 @@ export abstract class InputAssembler extends GFXObject { return this._indexBuffer; } - /** - * @en Get the indirect buffer, if present. - * @zh 间接绘制缓冲。 - */ - get indirectBuffer (): Buffer | null { - return this._indirectBuffer; - } - /** * @en Get hash of current attributes. * @zh 获取顶点属性数组的哈希值。 @@ -169,7 +161,6 @@ export abstract class InputAssembler extends GFXObject { protected _vertexBuffers: Buffer[] = []; protected _indexBuffer: Buffer | null = null; - protected _indirectBuffer: Buffer | null = null; protected _drawInfo = new DrawInfo(); diff --git a/cocos/gfx/webgl/webgl-buffer.ts b/cocos/gfx/webgl/webgl-buffer.ts index 9f6c308dc61..508e3e9c8c9 100644 --- a/cocos/gfx/webgl/webgl-buffer.ts +++ b/cocos/gfx/webgl/webgl-buffer.ts @@ -33,6 +33,7 @@ import { } from './webgl-commands'; import { IWebGLGPUBuffer, IWebGLGPUBufferView, WebGLIndirectDrawInfos } from './webgl-gpu-objects'; import { WebGLDeviceManager } from './webgl-define'; +import { warn } from '../../core/platform'; export class WebGLBuffer extends Buffer { get gpuBuffer (): IWebGLGPUBuffer { @@ -83,7 +84,6 @@ export class WebGLBuffer extends Buffer { stride: this._stride, buffer: null, vf32: null, - indirects: new WebGLIndirectDrawInfos(), glTarget: 0, glBuffer: null, }; @@ -112,7 +112,7 @@ export class WebGLBuffer extends Buffer { public resize (size: number): void { if (this._isBufferView) { - console.warn('cannot resize buffer views!'); + warn('cannot resize buffer views!'); return; } @@ -142,7 +142,7 @@ export class WebGLBuffer extends Buffer { public update (buffer: Readonly, size?: number): void { if (this._isBufferView) { - console.warn('cannot update through buffer views!'); + warn('cannot update through buffer views!'); return; } diff --git a/cocos/gfx/webgl/webgl-commands.ts b/cocos/gfx/webgl/webgl-commands.ts index f64ea3cc4ea..7355454b65b 100644 --- a/cocos/gfx/webgl/webgl-commands.ts +++ b/cocos/gfx/webgl/webgl-commands.ts @@ -782,12 +782,6 @@ export function WebGLCmdFuncUpdateBuffer ( } else { gpuBuffer.vf32!.set(new Float32Array(buffer as ArrayBuffer), offset / Float32Array.BYTES_PER_ELEMENT); } - } else if (gpuBuffer.usage & BufferUsageBit.INDIRECT) { - gpuBuffer.indirects.clearDraws(); - const drawInfos = (buffer as IndirectBuffer).drawInfos; - for (let i = 0; i < drawInfos.length; ++i) { - gpuBuffer.indirects.setDrawInfo(offset + i, drawInfos[i]); - } } else { const buff = buffer as ArrayBuffer; const { gl } = device; @@ -2590,83 +2584,7 @@ export function WebGLCmdFuncDraw (device: WebGLDevice, drawInfo: Readonly 0) { const offset = drawInfo.firstIndex * indexBuffer.stride; diff --git a/cocos/gfx/webgl/webgl-gpu-objects.ts b/cocos/gfx/webgl/webgl-gpu-objects.ts index 8abff6d139d..aa3e112e32a 100644 --- a/cocos/gfx/webgl/webgl-gpu-objects.ts +++ b/cocos/gfx/webgl/webgl-gpu-objects.ts @@ -131,7 +131,6 @@ export interface IWebGLGPUBuffer { buffer: ArrayBufferView | null; vf32: Float32Array | null; - indirects: WebGLIndirectDrawInfos; } export interface IWebGLGPUTexture { @@ -309,7 +308,6 @@ export interface IWebGLGPUInputAssembler { attributes: Attribute[]; gpuVertexBuffers: IWebGLGPUBuffer[]; gpuIndexBuffer: IWebGLGPUBuffer | null; - gpuIndirectBuffer: IWebGLGPUBuffer | null; glAttribs: IWebGLAttrib[]; glIndexType: GLenum; @@ -341,12 +339,16 @@ export class IWebGLBlitManager { this._gpuShader = { name: 'Blit Pass', blocks: [ - new UniformBlock(0, 0, `BlitParams`, + new UniformBlock( + 0, + 0, + `BlitParams`, [ new Uniform(`tilingOffsetSrc`, Type.FLOAT4, 1), new Uniform(`tilingOffsetDst`, Type.FLOAT4, 1), ], - 1), + 1, + ), ], samplerTextures: [new UniformSamplerTexture(0, samplerOffset, 'textureSrc', Type.SAMPLER2D, 1)], subpassInputs: [], @@ -430,7 +432,6 @@ export class IWebGLBlitManager { stride: 4 * Float32Array.BYTES_PER_ELEMENT, buffer: null, vf32: null, - indirects: new WebGLIndirectDrawInfos(), glTarget: 0, glBuffer: null, }; @@ -448,7 +449,6 @@ export class IWebGLBlitManager { attributes: [new Attribute(`a_position`, Format.RG32F), new Attribute(`a_texCoord`, Format.RG32F)], gpuVertexBuffers: [this._gpuVertexBuffer], gpuIndexBuffer: null, - gpuIndirectBuffer: null, glAttribs: [], glIndexType: 0, @@ -480,7 +480,6 @@ export class IWebGLBlitManager { stride: 8 * Float32Array.BYTES_PER_ELEMENT, buffer: this._uniformBuffer, vf32: null, - indirects: new WebGLIndirectDrawInfos(), glTarget: 0, glBuffer: null, }; @@ -538,7 +537,7 @@ export class IWebGLBlitManager { descriptor.gpuSampler = filter === Filter.POINT ? this._gpuPointSampler : this._gpuLinearSampler; const formatInfo = FormatInfos[gpuTextureDst.format]; - let attachment = gl.COLOR_ATTACHMENT0; + let attachment: number = gl.COLOR_ATTACHMENT0; if (formatInfo.hasStencil) { attachment = gl.DEPTH_STENCIL_ATTACHMENT; } else if (formatInfo.hasDepth) { @@ -582,8 +581,13 @@ export class IWebGLBlitManager { this._uniformBuffer[6] = region.dstOffset.x / dstWidth; this._uniformBuffer[7] = region.dstOffset.y / dstHeight; - WebGLCmdFuncUpdateBuffer(device, this._gpuUniformBuffer, this._uniformBuffer, 0, - this._uniformBuffer.length * Float32Array.BYTES_PER_ELEMENT); + WebGLCmdFuncUpdateBuffer( + device, + this._gpuUniformBuffer, + this._uniformBuffer, + 0, + this._uniformBuffer.length * Float32Array.BYTES_PER_ELEMENT, + ); WebGLCmdFuncBindStates(device, this._gpuPipelineState, this._gpuInputAssembler, [this._gpuDescriptorSet], [], null!); WebGLCmdFuncDraw(device, this._drawInfo); } diff --git a/cocos/gfx/webgl/webgl-input-assembler.ts b/cocos/gfx/webgl/webgl-input-assembler.ts index 58a188c6a4e..1d5a82bcc21 100644 --- a/cocos/gfx/webgl/webgl-input-assembler.ts +++ b/cocos/gfx/webgl/webgl-input-assembler.ts @@ -22,6 +22,7 @@ THE SOFTWARE. */ +import { error } from '../../core/platform'; import { InputAssemblerInfo } from '../base/define'; import { InputAssembler } from '../base/input-assembler'; import { WebGLBuffer } from './webgl-buffer'; @@ -38,7 +39,7 @@ export class WebGLInputAssembler extends InputAssembler { public initialize (info: Readonly): void { if (info.vertexBuffers.length === 0) { - console.error('InputAssemblerInfo.vertexBuffers is null.'); + error('InputAssemblerInfo.vertexBuffers is null.'); return; } @@ -59,8 +60,6 @@ export class WebGLInputAssembler extends InputAssembler { this._drawInfo.instanceCount = 0; this._drawInfo.firstInstance = 0; - this._indirectBuffer = info.indirectBuffer || null; - const gpuVertexBuffers: IWebGLGPUBuffer[] = new Array(info.vertexBuffers.length); for (let i = 0; i < info.vertexBuffers.length; ++i) { const vb = info.vertexBuffers[i] as WebGLBuffer; @@ -79,22 +78,16 @@ export class WebGLInputAssembler extends InputAssembler { case 2: glIndexType = 0x1403; break; // WebGLRenderingContext.UNSIGNED_SHORT case 4: glIndexType = 0x1405; break; // WebGLRenderingContext.UNSIGNED_INT default: { - console.error('Error index buffer stride.'); + error('Error index buffer stride.'); } } } } - let gpuIndirectBuffer: IWebGLGPUBuffer | null = null; - if (info.indirectBuffer) { - gpuIndirectBuffer = (info.indirectBuffer as WebGLBuffer).gpuBuffer; - } - this._gpuInputAssembler = { attributes: info.attributes, gpuVertexBuffers, gpuIndexBuffer, - gpuIndirectBuffer, glAttribs: [], glIndexType, diff --git a/cocos/gfx/webgl2/webgl2-buffer.ts b/cocos/gfx/webgl2/webgl2-buffer.ts index a9f868dd156..e119230ff21 100644 --- a/cocos/gfx/webgl2/webgl2-buffer.ts +++ b/cocos/gfx/webgl2/webgl2-buffer.ts @@ -22,6 +22,7 @@ THE SOFTWARE. */ +import { warn } from '../../core/platform'; import { Buffer } from '../base/buffer'; import { BufferUsageBit, BufferSource, BufferInfo, BufferViewInfo } from '../base/define'; import { @@ -58,7 +59,6 @@ export class WebGL2Buffer extends Buffer { size: this._size, stride: this._stride, buffer: null, - indirects: buffer.gpuBuffer.indirects, glTarget: buffer.gpuBuffer.glTarget, glBuffer: buffer.gpuBuffer.glBuffer, glOffset: info.offset, @@ -77,7 +77,6 @@ export class WebGL2Buffer extends Buffer { size: this._size, stride: this._stride, buffer: null, - indirects: new WebGL2IndirectDrawInfos(), glTarget: 0, glBuffer: null, glOffset: 0, @@ -101,7 +100,7 @@ export class WebGL2Buffer extends Buffer { public resize (size: number): void { if (this._isBufferView) { - console.warn('cannot resize buffer views!'); + warn('cannot resize buffer views!'); return; } @@ -123,7 +122,7 @@ export class WebGL2Buffer extends Buffer { public update (buffer: Readonly, size?: number): void { if (this._isBufferView) { - console.warn('cannot update through buffer views!'); + warn('cannot update through buffer views!'); return; } diff --git a/cocos/gfx/webgl2/webgl2-commands.ts b/cocos/gfx/webgl2/webgl2-commands.ts index 80f4caab35c..698558c8a6f 100644 --- a/cocos/gfx/webgl2/webgl2-commands.ts +++ b/cocos/gfx/webgl2/webgl2-commands.ts @@ -974,77 +974,69 @@ export function WebGL2CmdFuncUpdateBuffer ( offset: number, size: number, ): void { - if (gpuBuffer.usage & BufferUsageBit.INDIRECT) { - gpuBuffer.indirects.clearDraws(); - const drawInfos = (buffer as IndirectBuffer).drawInfos; - for (let i = 0; i < drawInfos.length; ++i) { - gpuBuffer.indirects.setDrawInfo(offset + i, drawInfos[i]); - } - } else { - const buff = buffer as ArrayBuffer; - const { gl } = device; - const cache = device.stateCache; - - switch (gpuBuffer.glTarget) { - case gl.ARRAY_BUFFER: { - if (device.extensions.useVAO) { - if (cache.glVAO) { - gl.bindVertexArray(null); - cache.glVAO = null; - } - } - gfxStateCache.gpuInputAssembler = null; + const buff = buffer as ArrayBuffer; + const { gl } = device; + const cache = device.stateCache; - if (cache.glArrayBuffer !== gpuBuffer.glBuffer) { - gl.bindBuffer(gl.ARRAY_BUFFER, gpuBuffer.glBuffer); - cache.glArrayBuffer = gpuBuffer.glBuffer; + switch (gpuBuffer.glTarget) { + case gl.ARRAY_BUFFER: { + if (device.extensions.useVAO) { + if (cache.glVAO) { + gl.bindVertexArray(null); + cache.glVAO = null; } + } + gfxStateCache.gpuInputAssembler = null; - if (size === buff.byteLength) { - gl.bufferSubData(gpuBuffer.glTarget, offset, buff); - } else { - gl.bufferSubData(gpuBuffer.glTarget, offset, buff.slice(0, size)); - } - break; + if (cache.glArrayBuffer !== gpuBuffer.glBuffer) { + gl.bindBuffer(gl.ARRAY_BUFFER, gpuBuffer.glBuffer); + cache.glArrayBuffer = gpuBuffer.glBuffer; } - case gl.ELEMENT_ARRAY_BUFFER: { - if (device.extensions.useVAO) { - if (cache.glVAO) { - gl.bindVertexArray(null); - cache.glVAO = null; - } - } - gfxStateCache.gpuInputAssembler = null; - if (cache.glElementArrayBuffer !== gpuBuffer.glBuffer) { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gpuBuffer.glBuffer); - cache.glElementArrayBuffer = gpuBuffer.glBuffer; + if (size === buff.byteLength) { + gl.bufferSubData(gpuBuffer.glTarget, offset, buff); + } else { + gl.bufferSubData(gpuBuffer.glTarget, offset, buff.slice(0, size)); + } + break; + } + case gl.ELEMENT_ARRAY_BUFFER: { + if (device.extensions.useVAO) { + if (cache.glVAO) { + gl.bindVertexArray(null); + cache.glVAO = null; } + } + gfxStateCache.gpuInputAssembler = null; - if (size === buff.byteLength) { - gl.bufferSubData(gpuBuffer.glTarget, offset, buff); - } else { - gl.bufferSubData(gpuBuffer.glTarget, offset, buff.slice(0, size)); - } - break; + if (cache.glElementArrayBuffer !== gpuBuffer.glBuffer) { + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gpuBuffer.glBuffer); + cache.glElementArrayBuffer = gpuBuffer.glBuffer; } - case gl.UNIFORM_BUFFER: { - if (cache.glUniformBuffer !== gpuBuffer.glBuffer) { - gl.bindBuffer(gl.UNIFORM_BUFFER, gpuBuffer.glBuffer); - cache.glUniformBuffer = gpuBuffer.glBuffer; - } - if (size === buff.byteLength) { - gl.bufferSubData(gpuBuffer.glTarget, offset, buff); - } else { - gl.bufferSubData(gpuBuffer.glTarget, offset, new Float32Array(buff, 0, size / 4)); - } - break; + if (size === buff.byteLength) { + gl.bufferSubData(gpuBuffer.glTarget, offset, buff); + } else { + gl.bufferSubData(gpuBuffer.glTarget, offset, buff.slice(0, size)); } - default: { - error('Unsupported BufferType, update buffer failed.'); + break; + } + case gl.UNIFORM_BUFFER: { + if (cache.glUniformBuffer !== gpuBuffer.glBuffer) { + gl.bindBuffer(gl.UNIFORM_BUFFER, gpuBuffer.glBuffer); + cache.glUniformBuffer = gpuBuffer.glBuffer; } + + if (size === buff.byteLength) { + gl.bufferSubData(gpuBuffer.glTarget, offset, buff); + } else { + gl.bufferSubData(gpuBuffer.glTarget, offset, new Float32Array(buff, 0, size / 4)); } + break; + } + default: { + error('Unsupported BufferType, update buffer failed.'); + } } } @@ -2649,83 +2641,7 @@ export function WebGL2CmdFuncDraw (device: WebGL2Device, drawInfo: Readonly 0) { const offset = drawInfo.firstIndex * indexBuffer.stride; diff --git a/cocos/gfx/webgl2/webgl2-gpu-objects.ts b/cocos/gfx/webgl2/webgl2-gpu-objects.ts index 1cdec040420..4204d6efb1d 100644 --- a/cocos/gfx/webgl2/webgl2-gpu-objects.ts +++ b/cocos/gfx/webgl2/webgl2-gpu-objects.ts @@ -119,7 +119,6 @@ export interface IWebGL2GPUBuffer { glOffset: number; buffer: ArrayBufferView | null; - indirects: WebGL2IndirectDrawInfos; } export interface IWebGL2GPUTexture { @@ -315,7 +314,6 @@ export interface IWebGL2GPUInputAssembler { attributes: Attribute[]; gpuVertexBuffers: IWebGL2GPUBuffer[]; gpuIndexBuffer: IWebGL2GPUBuffer | null; - gpuIndirectBuffer: IWebGL2GPUBuffer | null; glAttribs: IWebGL2Attrib[]; glIndexType: GLenum; diff --git a/cocos/gfx/webgl2/webgl2-input-assembler.ts b/cocos/gfx/webgl2/webgl2-input-assembler.ts index ec1e5566d9f..5f7859851bf 100644 --- a/cocos/gfx/webgl2/webgl2-input-assembler.ts +++ b/cocos/gfx/webgl2/webgl2-input-assembler.ts @@ -22,6 +22,7 @@ THE SOFTWARE. */ +import { error } from '../../core/platform'; import { InputAssemblerInfo } from '../base/define'; import { InputAssembler } from '../base/input-assembler'; import { WebGL2Buffer } from './webgl2-buffer'; @@ -38,7 +39,7 @@ export class WebGL2InputAssembler extends InputAssembler { public initialize (info: Readonly): void { if (info.vertexBuffers.length === 0) { - console.error('InputAssemblerInfo.vertexBuffers is null.'); + error('InputAssemblerInfo.vertexBuffers is null.'); return; } @@ -59,8 +60,6 @@ export class WebGL2InputAssembler extends InputAssembler { this._drawInfo.instanceCount = 0; this._drawInfo.firstInstance = 0; - this._indirectBuffer = info.indirectBuffer || null; - const gpuVertexBuffers: IWebGL2GPUBuffer[] = new Array(info.vertexBuffers.length); for (let i = 0; i < info.vertexBuffers.length; ++i) { const vb = info.vertexBuffers[i] as WebGL2Buffer; @@ -79,22 +78,16 @@ export class WebGL2InputAssembler extends InputAssembler { case 2: glIndexType = 0x1403; break; // WebGLRenderingContext.UNSIGNED_SHORT case 4: glIndexType = 0x1405; break; // WebGLRenderingContext.UNSIGNED_INT default: { - console.error('Illegal index buffer stride.'); + error('Illegal index buffer stride.'); } } } } - let gpuIndirectBuffer: IWebGL2GPUBuffer | null = null; - if (info.indirectBuffer) { - gpuIndirectBuffer = (info.indirectBuffer as WebGL2Buffer).gpuBuffer; - } - this._gpuInputAssembler = { attributes: info.attributes, gpuVertexBuffers, gpuIndexBuffer, - gpuIndirectBuffer, glAttribs: [], glIndexType, diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index d09e3b8a9fe..7e88c420aff 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -432,6 +432,9 @@ export class CopyPair { targetMostDetailedMip: number; targetFirstSlice: number; targetPlaneSlice: number; + sourceOffset = 0; + targetOffset = 0; + bufferSize = 0; } export class UploadPair { @@ -649,6 +652,9 @@ export function saveCopyPair (ar: OutputArchive, v: CopyPair): void { ar.writeNumber(v.targetMostDetailedMip); ar.writeNumber(v.targetFirstSlice); ar.writeNumber(v.targetPlaneSlice); + ar.writeNumber(v.sourceOffset); + ar.writeNumber(v.targetOffset); + ar.writeNumber(v.bufferSize); } export function loadCopyPair (ar: InputArchive, v: CopyPair): void { @@ -662,6 +668,9 @@ export function loadCopyPair (ar: InputArchive, v: CopyPair): void { v.targetMostDetailedMip = ar.readNumber(); v.targetFirstSlice = ar.readNumber(); v.targetPlaneSlice = ar.readNumber(); + v.sourceOffset = ar.readNumber(); + v.targetOffset = ar.readNumber(); + v.bufferSize = ar.readNumber(); } export function saveMovePair (ar: OutputArchive, v: MovePair): void { diff --git a/native/cocos/core/assets/RenderingSubMesh.cpp b/native/cocos/core/assets/RenderingSubMesh.cpp index 363414194ca..8b06882b852 100644 --- a/native/cocos/core/assets/RenderingSubMesh.cpp +++ b/native/cocos/core/assets/RenderingSubMesh.cpp @@ -70,7 +70,6 @@ RenderingSubMesh::RenderingSubMesh(const gfx::BufferList &vertexBuffers, _iaInfo.attributes = attributes; _iaInfo.vertexBuffers = vertexBuffers; _iaInfo.indexBuffer = indexBuffer; - _iaInfo.indirectBuffer = indirectBuffer; } RenderingSubMesh::~RenderingSubMesh() { diff --git a/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp b/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp index 7689387fd31..19d51fd7e3d 100644 --- a/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp +++ b/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp @@ -361,6 +361,38 @@ void CommandBufferAgent::draw(const DrawInfo &info) { }); } +void CommandBufferAgent::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) +{ + auto *bufferAgent = static_cast(buffer); + + ENQUEUE_MESSAGE_5( + _messageQueue, CommandBufferDrawIndirect, + actor, getActor(), + buff, bufferAgent->getActor(), + offset, offset, + count, count, + stride, stride, + { + actor->drawIndirect(buff, offset, count, stride); + }); +} + +void CommandBufferAgent::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) +{ + auto *bufferAgent = static_cast(buffer); + + ENQUEUE_MESSAGE_5( + _messageQueue, CommandBufferDrawIndexedIndirect, + actor, getActor(), + buff, bufferAgent->getActor(), + offset, offset, + count, count, + stride, stride, + { + actor->drawIndexedIndirect(buff, offset, count, stride); + }); +} + void CommandBufferAgent::updateBuffer(Buffer *buff, const void *data, uint32_t size) { auto *bufferAgent = static_cast(buff); @@ -425,6 +457,27 @@ void CommandBufferAgent::copyTexture(Texture *srcTexture, Texture *dstTexture, c }); } +void CommandBufferAgent::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + Buffer *actorSrcBuffer = nullptr; + Buffer *actorDstBuffer = nullptr; + if (srcBuffer) actorSrcBuffer = static_cast(srcBuffer)->getActor(); + if (dstBuffer) actorDstBuffer = static_cast(dstBuffer)->getActor(); + + auto *actorRegions = _messageQueue->allocate(count); + memcpy(actorRegions, regions, count * sizeof(BufferCopy)); + + ENQUEUE_MESSAGE_5( + _messageQueue, CommandBufferCopyBuffer, + actor, getActor(), + srcBuffer, actorSrcBuffer, + dstBuffer, actorDstBuffer, + regions, actorRegions, + count, count, + { + actor->copyBuffer(srcBuffer, dstBuffer, regions, count); + }); +} + void CommandBufferAgent::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { Texture *actorSrcTexture = nullptr; Texture *actorDstTexture = nullptr; diff --git a/native/cocos/renderer/gfx-agent/CommandBufferAgent.h b/native/cocos/renderer/gfx-agent/CommandBufferAgent.h index b3cf37ff0e8..d555e4d232a 100644 --- a/native/cocos/renderer/gfx-agent/CommandBufferAgent.h +++ b/native/cocos/renderer/gfx-agent/CommandBufferAgent.h @@ -57,10 +57,13 @@ class CC_DLL CommandBufferAgent final : public Agent { void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; diff --git a/native/cocos/renderer/gfx-agent/InputAssemblerAgent.cpp b/native/cocos/renderer/gfx-agent/InputAssemblerAgent.cpp index 1f7b9063aad..64b663c4888 100644 --- a/native/cocos/renderer/gfx-agent/InputAssemblerAgent.cpp +++ b/native/cocos/renderer/gfx-agent/InputAssemblerAgent.cpp @@ -54,9 +54,6 @@ void InputAssemblerAgent::doInit(const InputAssemblerInfo &info) { if (actorInfo.indexBuffer) { actorInfo.indexBuffer = static_cast(actorInfo.indexBuffer)->getActor(); } - if (actorInfo.indirectBuffer) { - actorInfo.indirectBuffer = static_cast(actorInfo.indirectBuffer)->getActor(); - } ENQUEUE_MESSAGE_2( DeviceAgent::getInstance()->getMessageQueue(), diff --git a/native/cocos/renderer/gfx-base/GFXCommandBuffer.h b/native/cocos/renderer/gfx-base/GFXCommandBuffer.h index 00a6d46e2aa..6225778fa9d 100644 --- a/native/cocos/renderer/gfx-base/GFXCommandBuffer.h +++ b/native/cocos/renderer/gfx-base/GFXCommandBuffer.h @@ -59,11 +59,14 @@ class CC_DLL CommandBuffer : public GFXObject, public RefCounted { virtual void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) = 0; virtual void nextSubpass() = 0; virtual void draw(const DrawInfo &info) = 0; + virtual void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) = 0; + virtual void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) = 0; virtual void updateBuffer(Buffer *buff, const void *data, uint32_t size) = 0; virtual void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) = 0; virtual void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) = 0; virtual void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) = 0; virtual void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) = 0; + virtual void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) = 0; virtual void execute(CommandBuffer *const *cmdBuffs, uint32_t count) = 0; virtual void dispatch(const DispatchInfo &info) = 0; virtual void beginQuery(QueryPool *queryPool, uint32_t id) = 0; diff --git a/native/cocos/renderer/gfx-base/GFXDef-common.h b/native/cocos/renderer/gfx-base/GFXDef-common.h index ab5c7bd810f..5af6e92cfa2 100644 --- a/native/cocos/renderer/gfx-base/GFXDef-common.h +++ b/native/cocos/renderer/gfx-base/GFXDef-common.h @@ -478,7 +478,8 @@ enum class TextureFlagBit : uint32_t { 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_STORAGE = 0x10, // Texture is mutable or not, default is immutable(only for webgl2) + LAZILY_ALLOCATED = 0x20, // Try lazily allocated mode. }; using TextureFlags = TextureFlagBit; CC_ENUM_BITWISE_OPERATORS(TextureFlagBit); @@ -852,6 +853,7 @@ struct DeviceCaps { bool supportQuery{false}; bool supportVariableRateShading{false}; bool supportSubPassShading{false}; + bool supportMultiDrawIndirect{false}; float clipSpaceMinZ{-1.F}; float screenSpaceSignY{1.F}; @@ -909,6 +911,14 @@ struct TextureSubresRange { EXPOSE_COPY_FN(TextureSubresRange) }; +struct BufferCopy { + uint32_t srcOffset{0}; + uint32_t dstOffset{0}; + uint32_t size{0}; + + EXPOSE_COPY_FN(BufferCopy) +}; + struct TextureCopy { TextureSubresLayers srcSubres; Offset srcOffset; @@ -1029,6 +1039,21 @@ struct BufferViewInfo { EXPOSE_COPY_FN(BufferViewInfo) }; +struct DrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +}; + +struct DrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +}; + struct DrawInfo { uint32_t vertexCount{0}; uint32_t firstVertex{0}; @@ -1272,7 +1297,6 @@ struct InputAssemblerInfo { AttributeList attributes; BufferList vertexBuffers; Buffer *indexBuffer{nullptr}; // @ts-nullable - Buffer *indirectBuffer{nullptr}; // @ts-nullable EXPOSE_COPY_FN(InputAssemblerInfo) }; diff --git a/native/cocos/renderer/gfx-base/GFXDef.cpp b/native/cocos/renderer/gfx-base/GFXDef.cpp index 00a9bc6873e..822823c2e68 100644 --- a/native/cocos/renderer/gfx-base/GFXDef.cpp +++ b/native/cocos/renderer/gfx-base/GFXDef.cpp @@ -644,6 +644,19 @@ uint32_t formatSurfaceSize(Format format, uint32_t width, uint32_t height, uint3 return size; } +ccstd::hash_t computeAttributesHash(const AttributeList& attributes) { + ccstd::hash_t seed = static_cast(attributes.size()) * 6; + for (const auto &attribute : attributes) { + ccstd::hash_combine(seed, attribute.name); + ccstd::hash_combine(seed, attribute.format); + ccstd::hash_combine(seed, attribute.isNormalized); + ccstd::hash_combine(seed, attribute.stream); + ccstd::hash_combine(seed, attribute.isInstanced); + ccstd::hash_combine(seed, attribute.location); + } + return seed; +} + uint32_t gcd(uint32_t a, uint32_t b) { while (b) { uint32_t t = a % b; diff --git a/native/cocos/renderer/gfx-base/GFXDef.h b/native/cocos/renderer/gfx-base/GFXDef.h index 780ac44c065..9e0cf77ad8a 100644 --- a/native/cocos/renderer/gfx-base/GFXDef.h +++ b/native/cocos/renderer/gfx-base/GFXDef.h @@ -135,6 +135,8 @@ uint32_t formatSize(Format format, uint32_t width, uint32_t height, uint32_t dep uint32_t formatSurfaceSize(Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t mips); +ccstd::hash_t computeAttributesHash(const AttributeList &attributes); + /** * @en Get the memory size of the specified type. * @zh 得到 GFX 数据类型的大小。 diff --git a/native/cocos/renderer/gfx-base/GFXInputAssembler.cpp b/native/cocos/renderer/gfx-base/GFXInputAssembler.cpp index dc6a1da58fe..616b6851e7c 100644 --- a/native/cocos/renderer/gfx-base/GFXInputAssembler.cpp +++ b/native/cocos/renderer/gfx-base/GFXInputAssembler.cpp @@ -22,8 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/std/hash/hash.h" - +#include "GFXDef.h" #include "GFXBuffer.h" #include "GFXInputAssembler.h" #include "GFXObject.h" @@ -37,25 +36,11 @@ InputAssembler::InputAssembler() InputAssembler::~InputAssembler() = default; -ccstd::hash_t InputAssembler::computeAttributesHash() const { - ccstd::hash_t seed = static_cast(_attributes.size()) * 6; - for (const auto &attribute : _attributes) { - ccstd::hash_combine(seed, attribute.name); - ccstd::hash_combine(seed, attribute.format); - ccstd::hash_combine(seed, attribute.isNormalized); - ccstd::hash_combine(seed, attribute.stream); - ccstd::hash_combine(seed, attribute.isInstanced); - ccstd::hash_combine(seed, attribute.location); - } - return seed; -} - void InputAssembler::initialize(const InputAssemblerInfo &info) { _attributes = info.attributes; _vertexBuffers = info.vertexBuffers; _indexBuffer = info.indexBuffer; - _indirectBuffer = info.indirectBuffer; - _attributesHash = computeAttributesHash(); + _attributesHash = computeAttributesHash(_attributes); if (_indexBuffer) { _drawInfo.indexCount = _indexBuffer->getCount(); @@ -77,7 +62,6 @@ void InputAssembler::destroy() { _vertexBuffers.clear(); _indexBuffer = nullptr; - _indirectBuffer = nullptr; _drawInfo = DrawInfo(); } diff --git a/native/cocos/renderer/gfx-base/GFXInputAssembler.h b/native/cocos/renderer/gfx-base/GFXInputAssembler.h index 6d50248aa93..0400ab5e9b8 100644 --- a/native/cocos/renderer/gfx-base/GFXInputAssembler.h +++ b/native/cocos/renderer/gfx-base/GFXInputAssembler.h @@ -41,7 +41,6 @@ class CC_DLL InputAssembler : public GFXObject, public RefCounted { inline const AttributeList &getAttributes() const { return _attributes; } inline const BufferList &getVertexBuffers() const { return _vertexBuffers; } inline Buffer *getIndexBuffer() const { return _indexBuffer; } - inline Buffer *getIndirectBuffer() const { return _indirectBuffer; } inline ccstd::hash_t getAttributesHash() const { return _attributesHash; } inline const DrawInfo &getDrawInfo() const { return _drawInfo; } @@ -67,14 +66,11 @@ class CC_DLL InputAssembler : public GFXObject, public RefCounted { virtual void doInit(const InputAssemblerInfo &info) = 0; virtual void doDestroy() = 0; - ccstd::hash_t computeAttributesHash() const; - AttributeList _attributes; ccstd::hash_t _attributesHash = 0; BufferList _vertexBuffers; Buffer *_indexBuffer{nullptr}; - Buffer *_indirectBuffer{nullptr}; DrawInfo _drawInfo; }; diff --git a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp index 8c2e17a36b1..08f8bdb9489 100644 --- a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp @@ -87,6 +87,12 @@ void EmptyCommandBuffer::nextSubpass() { void EmptyCommandBuffer::draw(const DrawInfo &info) { } +void EmptyCommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { +} + +void EmptyCommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { +} + void EmptyCommandBuffer::updateBuffer(Buffer *buff, const void *data, uint32_t size) { } @@ -102,6 +108,9 @@ void EmptyCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, c void EmptyCommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) { } +void EmptyCommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { +} + void EmptyCommandBuffer::dispatch(const DispatchInfo &info) { } diff --git a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h index d429d23f61c..49853368838 100644 --- a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h +++ b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h @@ -48,11 +48,14 @@ class CC_DLL EmptyCommandBuffer final : public CommandBuffer { void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override; diff --git a/native/cocos/renderer/gfx-gles2/GLES2Buffer.cpp b/native/cocos/renderer/gfx-gles2/GLES2Buffer.cpp index 70e8834239a..111584c8b73 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2Buffer.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2Buffer.cpp @@ -48,10 +48,6 @@ void GLES2Buffer::doInit(const BufferInfo & /*info*/) { _gpuBuffer->stride = _stride; _gpuBuffer->count = _count; - if (hasFlag(_usage, BufferUsageBit::INDIRECT)) { - _gpuBuffer->indirects.resize(_count); - } - cmdFuncGLES2CreateBuffer(GLES2Device::getInstance(), _gpuBuffer); GLES2Device::getInstance()->getMemoryStatus().bufferSize += _size; CC_PROFILE_MEMORY_INC(Buffer, _size); diff --git a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp index daaf4efc6e9..85880ccead9 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp @@ -254,6 +254,22 @@ void GLES2CommandBuffer::setStencilCompareMask(StencilFace face, uint32_t ref, u if (hasFlag(face, StencilFace::BACK)) update(_curDynamicStates.stencilStatesBack); } +void GLES2CommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + // not support + std::ignore = buffer; + std::ignore = offset; + std::ignore = count; + std::ignore = stride; +} + +void GLES2CommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + // not support + std::ignore = buffer; + std::ignore = offset; + std::ignore = count; + std::ignore = stride; +} + void GLES2CommandBuffer::draw(const DrawInfo &info) { CC_PROFILE(GLES2CommandBufferDraw); if (_isStateInvalid) { @@ -320,6 +336,10 @@ void GLES2CommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture // should not copy texture in a secondary command buffer } +void GLES2CommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + // should not copy buffer in a secondary command buffer +} + void GLES2CommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { GLES2CmdBlitTexture *cmd = _cmdAllocator->blitTextureCmdPool.alloc(); if (srcTexture) cmd->gpuTextureSrc = static_cast(srcTexture)->gpuTexture(); diff --git a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h index 06185861895..12bc12d8b31 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h +++ b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h @@ -61,11 +61,14 @@ class CC_GLES2_API GLES2CommandBuffer : public CommandBuffer { void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override {} void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override {} diff --git a/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp b/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp index 1d9ca68f441..b1f685e0cd0 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp @@ -554,7 +554,6 @@ void cmdFuncGLES2ResizeBuffer(GLES2Device *device, GLES2GPUBuffer *gpuBuffer) { device->stateCache()->glElementArrayBuffer = 0; } } else if (hasFlag(gpuBuffer->usage, BufferUsageBit::INDIRECT)) { - gpuBuffer->indirects.resize(gpuBuffer->count); gpuBuffer->glTarget = GL_NONE; } else if ((hasFlag(gpuBuffer->usage, BufferUsageBit::UNIFORM)) || (hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_DST)) || @@ -2596,51 +2595,24 @@ void cmdFuncGLES2Draw(GLES2Device *device, const DrawInfo &drawInfo) { GLenum glPrimitive = gfxStateCache.glPrimitive; if (gpuInputAssembler && gpuPipelineState) { - if (!gpuInputAssembler->gpuIndirectBuffer) { - if (gpuInputAssembler->gpuIndexBuffer) { - if (drawInfo.indexCount > 0) { - uint8_t *offset = nullptr; - offset += drawInfo.firstIndex * gpuInputAssembler->gpuIndexBuffer->stride; - if (drawInfo.instanceCount == 0) { - GL_CHECK(glDrawElements(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset)); - } else { - if (device->constantRegistry()->useDrawInstanced) { - GL_CHECK(glDrawElementsInstancedEXT(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset, drawInfo.instanceCount)); - } - } - } - } else if (drawInfo.vertexCount > 0) { + if (gpuInputAssembler->gpuIndexBuffer) { + if (drawInfo.indexCount > 0) { + uint8_t *offset = nullptr; + offset += drawInfo.firstIndex * gpuInputAssembler->gpuIndexBuffer->stride; if (drawInfo.instanceCount == 0) { - GL_CHECK(glDrawArrays(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount)); + GL_CHECK(glDrawElements(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset)); } else { if (device->constantRegistry()->useDrawInstanced) { - GL_CHECK(glDrawArraysInstancedEXT(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount, drawInfo.instanceCount)); + GL_CHECK(glDrawElementsInstancedEXT(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset, drawInfo.instanceCount)); } } } - } else { - for (size_t j = 0; j < gpuInputAssembler->gpuIndirectBuffer->indirects.size(); ++j) { - const DrawInfo &draw = gpuInputAssembler->gpuIndirectBuffer->indirects[j]; - if (gpuInputAssembler->gpuIndexBuffer) { - if (draw.indexCount > 0) { - uint8_t *offset = nullptr; - offset += draw.firstIndex * gpuInputAssembler->gpuIndexBuffer->stride; - if (drawInfo.instanceCount == 0) { - GL_CHECK(glDrawElements(glPrimitive, draw.indexCount, gpuInputAssembler->glIndexType, offset)); - } else { - if (device->constantRegistry()->useDrawInstanced) { - GL_CHECK(glDrawElementsInstancedEXT(glPrimitive, draw.indexCount, gpuInputAssembler->glIndexType, offset, draw.instanceCount)); - } - } - } - } else if (draw.vertexCount > 0) { - if (draw.instanceCount == 0) { - GL_CHECK(glDrawArrays(glPrimitive, draw.firstVertex, draw.vertexCount)); - } else { - if (device->constantRegistry()->useDrawInstanced) { - GL_CHECK(glDrawArraysInstancedEXT(glPrimitive, draw.firstVertex, draw.vertexCount, draw.instanceCount)); - } - } + } else if (drawInfo.vertexCount > 0) { + if (drawInfo.instanceCount == 0) { + GL_CHECK(glDrawArrays(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount)); + } else { + if (device->constantRegistry()->useDrawInstanced) { + GL_CHECK(glDrawArraysInstancedEXT(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount, drawInfo.instanceCount)); } } } @@ -2653,8 +2625,6 @@ void cmdFuncGLES2UpdateBuffer(GLES2Device *device, GLES2GPUBuffer *gpuBuffer, co if ((hasFlag(gpuBuffer->usage, BufferUsageBit::UNIFORM)) || (hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_SRC))) { memcpy(gpuBuffer->buffer + offset, buffer, size); - } else if (hasFlag(gpuBuffer->usage, BufferUsageBit::INDIRECT)) { - memcpy(reinterpret_cast(gpuBuffer->indirects.data()) + offset, buffer, size); } else { switch (gpuBuffer->glTarget) { case GL_ARRAY_BUFFER: { diff --git a/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h b/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h index 99ce522f08d..b5b31eac436 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h +++ b/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h @@ -98,7 +98,6 @@ struct GLES2GPUBuffer { GLenum glTarget = 0; GLuint glBuffer = 0; uint8_t *buffer = nullptr; - DrawInfoList indirects; }; using GLES2GPUBufferList = ccstd::vector; @@ -251,7 +250,6 @@ struct GLES2GPUInputAssembler { AttributeList attributes; GLES2GPUBufferList gpuVertexBuffers; GLES2GPUBuffer *gpuIndexBuffer = nullptr; - GLES2GPUBuffer *gpuIndirectBuffer = nullptr; GLES2GPUAttributeList glAttribs; GLenum glIndexType = 0; ccstd::unordered_map glVAOs; diff --git a/native/cocos/renderer/gfx-gles2/GLES2InputAssembler.cpp b/native/cocos/renderer/gfx-gles2/GLES2InputAssembler.cpp index 1599cf842c5..ca6567f1431 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2InputAssembler.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2InputAssembler.cpp @@ -52,10 +52,6 @@ void GLES2InputAssembler::doInit(const InputAssemblerInfo &info) { _gpuInputAssembler->gpuIndexBuffer = static_cast(info.indexBuffer)->gpuBuffer(); } - if (info.indirectBuffer) { - _gpuInputAssembler->gpuIndirectBuffer = static_cast(info.indirectBuffer)->gpuBuffer(); - } - cmdFuncGLES2CreateInputAssembler(GLES2Device::getInstance(), _gpuInputAssembler); } diff --git a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp index 1c3832849a8..973fb81b031 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp @@ -80,6 +80,22 @@ void GLES2PrimaryCommandBuffer::nextSubpass() { cmdFuncGLES2BeginRenderPass(GLES2Device::getInstance(), ++_curSubpassIdx); } +void GLES2PrimaryCommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + // not support + std::ignore = buffer; + std::ignore = offset; + std::ignore = count; + std::ignore = stride; +} + +void GLES2PrimaryCommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + // not support + std::ignore = buffer; + std::ignore = offset; + std::ignore = count; + std::ignore = stride; +} + void GLES2PrimaryCommandBuffer::draw(const DrawInfo &info) { CC_PROFILE(GLES2PrimaryCommandBufferDraw); if (_isStateInvalid) { @@ -175,6 +191,9 @@ void GLES2PrimaryCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTex cmdFuncGLES2BlitTexture(GLES2Device::getInstance(), gpuTextureSrc, gpuTextureDst, blitRegions.data(), count, Filter::POINT); } +void GLES2PrimaryCommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { +} + void GLES2PrimaryCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { GLES2GPUTexture *gpuTextureSrc = nullptr; GLES2GPUTexture *gpuTextureDst = nullptr; diff --git a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h index 2a3411c9eef..299c0e362c3 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h +++ b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h @@ -40,6 +40,8 @@ class CC_GLES2_API GLES2PrimaryCommandBuffer final : public GLES2CommandBuffer { void endRenderPass() override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void setViewport(const Viewport &vp) override; void setScissor(const Rect &rect) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; @@ -47,6 +49,7 @@ class CC_GLES2_API GLES2PrimaryCommandBuffer final : public GLES2CommandBuffer { void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; protected: diff --git a/native/cocos/renderer/gfx-gles3/GLES3Buffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3Buffer.cpp index dfaa7b8f496..f8d6a86b38e 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Buffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Buffer.cpp @@ -48,10 +48,6 @@ void GLES3Buffer::doInit(const BufferInfo & /*info*/) { _gpuBuffer->stride = _stride; _gpuBuffer->count = _count; - if (hasFlag(_usage, BufferUsageBit::INDIRECT)) { - _gpuBuffer->indirects.resize(_count); - } - cmdFuncGLES3CreateBuffer(GLES3Device::getInstance(), _gpuBuffer); GLES3Device::getInstance()->getMemoryStatus().bufferSize += _size; CC_PROFILE_MEMORY_INC(Buffer, _size); @@ -68,8 +64,6 @@ void GLES3Buffer::doInit(const BufferViewInfo &info) { _gpuBuffer->glTarget = buffer->_gpuBuffer->glTarget; _gpuBuffer->glBuffer = buffer->_gpuBuffer->glBuffer; _gpuBuffer->glOffset = info.offset; - _gpuBuffer->buffer = buffer->_gpuBuffer->buffer; - _gpuBuffer->indirects = buffer->_gpuBuffer->indirects; } void GLES3Buffer::doDestroy() { diff --git a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp index 706dd795a59..182b76ae343 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp @@ -255,6 +255,20 @@ void GLES3CommandBuffer::setStencilCompareMask(StencilFace face, uint32_t ref, u if (hasFlag(face, StencilFace::BACK)) update(_curDynamicStates.stencilStatesBack); } +void GLES3CommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + // not support + std::ignore = buffer; + std::ignore = offset; + std::ignore = count; + std::ignore = stride; +} +void GLES3CommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + // not support + std::ignore = buffer; + std::ignore = offset; + std::ignore = count; + std::ignore = stride; +} void GLES3CommandBuffer::draw(const DrawInfo &info) { CC_PROFILE(GLES3CommandBufferDraw); if (_isStateInvalid) { @@ -307,6 +321,10 @@ void GLES3CommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture // should not resolve texture in a secondary command buffer } +void GLES3CommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + // should not copy buffer in a secondary command buffer +} + void GLES3CommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { GLES3CmdBlitTexture *cmd = _cmdAllocator->blitTextureCmdPool.alloc(); if (srcTexture) cmd->gpuTextureSrc = static_cast(srcTexture)->gpuTexture(); diff --git a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h index d42b50d43bc..2f08d4accee 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h +++ b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h @@ -60,11 +60,14 @@ class CC_GLES3_API GLES3CommandBuffer : public CommandBuffer { void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const * /*buffers*/, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const * /*textures*/, uint32_t textureBarrierCount) override; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp index afddfc2d1a7..d08f3e60768 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp @@ -658,11 +658,15 @@ void cmdFuncGLES3CreateBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer) { device->stateCache()->glShaderStorageBuffer = 0; } } else if (hasFlag(gpuBuffer->usage, BufferUsageBit::INDIRECT)) { - gpuBuffer->glTarget = GL_NONE; - } else if ((hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_DST)) || - (hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_SRC))) { - gpuBuffer->buffer = static_cast(CC_MALLOC(gpuBuffer->size)); - gpuBuffer->glTarget = GL_NONE; + gpuBuffer->glTarget = GL_DRAW_INDIRECT_BUFFER; + GL_CHECK(glGenBuffers(1, &gpuBuffer->glBuffer)); + if (device->stateCache()->glDrawIndirectBuffer != gpuBuffer->glBuffer) { + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, gpuBuffer->glBuffer)); + } + + GL_CHECK(glBufferData(GL_DRAW_INDIRECT_BUFFER, gpuBuffer->size, nullptr, glUsage)); + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0)); + device->stateCache()->glDrawIndirectBuffer = 0; } else { CC_ABORT(); gpuBuffer->glTarget = GL_NONE; @@ -786,8 +790,16 @@ void cmdFuncGLES3ResizeBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer) { device->stateCache()->glUniformBuffer = 0; } } else if (hasFlag(gpuBuffer->usage, BufferUsageBit::INDIRECT)) { - gpuBuffer->indirects.resize(gpuBuffer->count); - gpuBuffer->glTarget = GL_NONE; + gpuBuffer->glTarget = GL_DRAW_INDIRECT_BUFFER; + if (gpuBuffer->size) { + if (device->stateCache()->glDrawIndirectBuffer != gpuBuffer->glBuffer) { + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, gpuBuffer->glBuffer)); + } + + GL_CHECK(glBufferData(GL_DRAW_INDIRECT_BUFFER, gpuBuffer->size, nullptr, glUsage)); + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0)); + device->stateCache()->glDrawIndirectBuffer = 0; + } } else if ((hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_DST)) || (hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_SRC))) { if (gpuBuffer->buffer) { @@ -2468,6 +2480,41 @@ void cmdFuncGLES3BindState(GLES3Device *device, GLES3GPUPipelineState *gpuPipeli } } +void cmdFuncGLES3DrawIndirect(GLES3Device *device, + GLES3GPUBuffer *gpuBuffer, + uint32_t offset, + uint32_t count, + uint32_t stride, + bool indexed) { + uint32_t bufferOffset = gpuBuffer->glOffset + offset; + GLES3GPUStateCache *cache = device->stateCache(); + GLenum primitive = cache->gfxStateCache.glPrimitive; + + if (cache->glDrawIndirectBuffer != gpuBuffer->glBuffer) { + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, gpuBuffer->glBuffer)); + cache->glDrawIndirectBuffer = gpuBuffer->glBuffer; + } + + uint8_t *ptr = nullptr; + if (device->constantRegistry()->multiDrawIndirect) { + if (indexed) { + GL_CHECK(glMultiDrawElementsIndirectEXT(primitive, cache->gfxStateCache.gpuInputAssembler->glIndexType, + ptr + bufferOffset, count, stride)); + } else { + GL_CHECK(glMultiDrawArraysIndirectEXT(primitive, ptr + bufferOffset, count, stride)); + } + } else { + for (uint32_t i = 0U; i < count; ++i) { + uint32_t currentOffset = bufferOffset + i * stride; + if (indexed) { + GL_CHECK(glDrawElementsIndirect(primitive, cache->gfxStateCache.gpuInputAssembler->glIndexType, ptr + currentOffset)); + } else { + GL_CHECK(glDrawArraysIndirect(primitive, ptr + currentOffset)); + } + } + } +} + void cmdFuncGLES3Draw(GLES3Device *device, const DrawInfo &drawInfo) { GLES3ObjectCache &gfxStateCache = device->stateCache()->gfxStateCache; GLES3GPUPipelineState *gpuPipelineState = gfxStateCache.gpuPipelineState; @@ -2475,44 +2522,21 @@ void cmdFuncGLES3Draw(GLES3Device *device, const DrawInfo &drawInfo) { GLenum glPrimitive = gfxStateCache.glPrimitive; if (gpuInputAssembler && gpuPipelineState) { - if (!gpuInputAssembler->gpuIndirectBuffer) { - if (gpuInputAssembler->gpuIndexBuffer) { - if (drawInfo.indexCount > 0) { - uint8_t *offset = nullptr; - offset += drawInfo.firstIndex * gpuInputAssembler->gpuIndexBuffer->stride; - if (drawInfo.instanceCount == 0) { - GL_CHECK(glDrawElements(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset)); - } else { - GL_CHECK(glDrawElementsInstanced(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset, drawInfo.instanceCount)); - } - } - } else if (drawInfo.vertexCount > 0) { + if (gpuInputAssembler->gpuIndexBuffer) { + if (drawInfo.indexCount > 0) { + uint8_t *offset = nullptr; + offset += drawInfo.firstIndex * gpuInputAssembler->gpuIndexBuffer->stride; if (drawInfo.instanceCount == 0) { - GL_CHECK(glDrawArrays(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount)); + GL_CHECK(glDrawElements(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset)); } else { - GL_CHECK(glDrawArraysInstanced(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount, drawInfo.instanceCount)); + GL_CHECK(glDrawElementsInstanced(glPrimitive, drawInfo.indexCount, gpuInputAssembler->glIndexType, offset, drawInfo.instanceCount)); } } - } else { - for (size_t j = 0; j < gpuInputAssembler->gpuIndirectBuffer->indirects.size(); ++j) { - const DrawInfo &draw = gpuInputAssembler->gpuIndirectBuffer->indirects[j]; - if (gpuInputAssembler->gpuIndexBuffer) { - if (draw.indexCount > 0) { - uint8_t *offset = nullptr; - offset += draw.firstIndex * gpuInputAssembler->gpuIndexBuffer->stride; - if (draw.instanceCount == 0) { - GL_CHECK(glDrawElements(glPrimitive, draw.indexCount, gpuInputAssembler->glIndexType, offset)); - } else { - GL_CHECK(glDrawElementsInstanced(glPrimitive, draw.indexCount, gpuInputAssembler->glIndexType, offset, draw.instanceCount)); - } - } - } else if (draw.vertexCount > 0) { - if (draw.instanceCount == 0) { - GL_CHECK(glDrawArrays(glPrimitive, draw.firstVertex, draw.vertexCount)); - } else { - GL_CHECK(glDrawArraysInstanced(glPrimitive, draw.firstVertex, draw.vertexCount, draw.instanceCount)); - } - } + } else if (drawInfo.vertexCount > 0) { + if (drawInfo.instanceCount == 0) { + GL_CHECK(glDrawArrays(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount)); + } else { + GL_CHECK(glDrawArraysInstanced(glPrimitive, drawInfo.firstVertex, drawInfo.vertexCount, drawInfo.instanceCount)); } } } @@ -2553,9 +2577,7 @@ static void uploadBufferData(GLenum target, GLintptr offset, GLsizeiptr length, void cmdFuncGLES3UpdateBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer, const void *buffer, uint32_t offset, uint32_t size) { GLES3ObjectCache &gfxStateCache = device->stateCache()->gfxStateCache; - if (hasFlag(gpuBuffer->usage, BufferUsageBit::INDIRECT)) { - memcpy(reinterpret_cast(gpuBuffer->indirects.data()) + offset, buffer, size); - } else if (hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_SRC) && gpuBuffer->buffer != nullptr) { + if (hasFlag(gpuBuffer->usage, BufferUsageBit::TRANSFER_SRC) && gpuBuffer->buffer != nullptr) { memcpy(gpuBuffer->buffer + offset, buffer, size); } else { switch (gpuBuffer->glTarget) { @@ -2601,6 +2623,14 @@ void cmdFuncGLES3UpdateBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer, co uploadBufferData(GL_SHADER_STORAGE_BUFFER, offset, size, buffer); break; } + case GL_DRAW_INDIRECT_BUFFER: { + if (device->stateCache()->glDrawIndirectBuffer != gpuBuffer->glBuffer) { + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, gpuBuffer->glBuffer)); + device->stateCache()->glDrawIndirectBuffer = gpuBuffer->glBuffer; + } + uploadBufferData(GL_DRAW_INDIRECT_BUFFER, offset, size, buffer); + break; + } default: CC_ABORT(); break; @@ -2924,6 +2954,21 @@ void cmdFuncGLES3BlitTexture(GLES3Device *device, GLES3GPUTexture *gpuTextureSrc } } +void cmdFuncGLES3CopyBuffer(GLES3GPUBuffer *gpuBufferSrc,GLES3GPUBuffer *gpuBufferDst, + const BufferCopy *regions, uint32_t count) { + GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, gpuBufferSrc->glBuffer)); + GL_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, gpuBufferDst->glBuffer)); + + for (uint32_t i = 0; i < count; ++i) { + const auto © = regions[i]; + GL_CHECK(glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, + copy.srcOffset, copy.dstOffset, copy.size)); + } + + GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, 0)); + GL_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, 0)); +} + void cmdFuncGLES3ExecuteCmds(GLES3Device *device, GLES3CmdPackage *cmdPackage) { if (!cmdPackage->cmds.size()) return; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.h b/native/cocos/renderer/gfx-gles3/GLES3Commands.h index c9d612550de..e8e1f6a8725 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.h +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.h @@ -281,6 +281,12 @@ void cmdFuncGLES3BindState(GLES3Device *device, const DynamicStates *dynamicStates = nullptr); void cmdFuncGLES3Draw(GLES3Device *device, const DrawInfo &drawInfo); +void cmdFuncGLES3DrawIndirect(GLES3Device *device, + GLES3GPUBuffer *gpuBuffer, + uint32_t offset, + uint32_t count, + uint32_t stride, + bool indexed); void cmdFuncGLES3UpdateBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer, @@ -306,6 +312,11 @@ void cmdFuncGLES3BlitTexture(GLES3Device *device, uint32_t count, Filter filter); +void cmdFuncGLES3CopyBuffer(GLES3GPUBuffer *gpuBufferSrc, + GLES3GPUBuffer *gpuBufferDst, + const BufferCopy *regions, + uint32_t count); + void cmdFuncGLES3ExecuteCmds(GLES3Device *device, GLES3CmdPackage *cmdPackage); void cmdFuncGLES3Dispatch(GLES3Device *device, const GLES3GPUDispatchInfo &info); diff --git a/native/cocos/renderer/gfx-gles3/GLES3Device.cpp b/native/cocos/renderer/gfx-gles3/GLES3Device.cpp index 79bc6937af8..c5e1bdfc4af 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Device.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Device.cpp @@ -152,6 +152,7 @@ bool GLES3Device::doInit(const DeviceInfo & /*info*/) { _features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = true; fbfLevelStr += "_DEPTH_STENCIL"; } + _gpuConstantRegistry->multiDrawIndirect = checkExtension((CC_TOSTR(multi_draw_indirect))); ccstd::string msaaLevelStr = "NONE"; #if CC_PLATFORM != CC_PLATFORM_WINDOWS || ALLOW_MULTISAMPLED_RENDER_TO_TEXTURE_ON_DESKTOP diff --git a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h index 169767fe082..7aeebdb6e7b 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h +++ b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h @@ -43,6 +43,7 @@ struct GLES3GPUConstantRegistry { MSRTSupportLevel mMSRT{MSRTSupportLevel::NONE}; FBFSupportLevel mFBF{FBFSupportLevel::NONE}; + uint32_t multiDrawIndirect = false; }; class GLES3GPUStateCache; @@ -116,7 +117,6 @@ struct GLES3GPUBuffer { GLuint glBuffer = 0; GLuint glOffset = 0; uint8_t *buffer = nullptr; - DrawInfoList indirects; }; using GLES3GPUBufferList = ccstd::vector; @@ -307,7 +307,6 @@ struct GLES3GPUInputAssembler { AttributeList attributes; GLES3GPUBufferList gpuVertexBuffers; GLES3GPUBuffer *gpuIndexBuffer = nullptr; - GLES3GPUBuffer *gpuIndirectBuffer = nullptr; GLES3GPUAttributeList glAttribs; GLenum glIndexType = 0; ccstd::unordered_map glVAOs; @@ -460,6 +459,7 @@ class GLES3GPUStateCache final { ccstd::vector glBindSSBOs; ccstd::vector glBindSSBOOffsets; GLuint glDispatchIndirectBuffer = 0; + GLuint glDrawIndirectBuffer = 0; GLuint glVAO = 0; uint32_t texUint = 0; ccstd::vector glTextures; @@ -506,6 +506,7 @@ class GLES3GPUStateCache final { glBindSSBOs.assign(glBindSSBOs.size(), 0U); glBindSSBOOffsets.assign(glBindSSBOOffsets.size(), 0U); glDispatchIndirectBuffer = 0; + glDrawIndirectBuffer = 0; glVAO = 0; texUint = 0; glTextures.assign(glTextures.size(), 0U); diff --git a/native/cocos/renderer/gfx-gles3/GLES3InputAssembler.cpp b/native/cocos/renderer/gfx-gles3/GLES3InputAssembler.cpp index c988df02020..bdd55424055 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3InputAssembler.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3InputAssembler.cpp @@ -52,10 +52,6 @@ void GLES3InputAssembler::doInit(const InputAssemblerInfo &info) { _gpuInputAssembler->gpuIndexBuffer = static_cast(info.indexBuffer)->gpuBuffer(); } - if (info.indirectBuffer) { - _gpuInputAssembler->gpuIndirectBuffer = static_cast(info.indirectBuffer)->gpuBuffer(); - } - cmdFuncGLES3CreateInputAssembler(GLES3Device::getInstance(), _gpuInputAssembler); } diff --git a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp index c409f6023a8..4b9c5e4cabd 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp @@ -80,6 +80,26 @@ void GLES3PrimaryCommandBuffer::nextSubpass() { ++_curSubpassIdx; } +void GLES3PrimaryCommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + if (_isStateInvalid) { + bindStates(); + } + + auto *glesBuffer = static_cast(buffer); + auto *gpuBuffer = glesBuffer->gpuBuffer(); + cmdFuncGLES3DrawIndirect(GLES3Device::getInstance(), gpuBuffer, offset, count, stride, false); +} + +void GLES3PrimaryCommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + if (_isStateInvalid) { + bindStates(); + } + + auto *glesBuffer = static_cast(buffer); + auto *gpuBuffer = glesBuffer->gpuBuffer(); + cmdFuncGLES3DrawIndirect(GLES3Device::getInstance(), gpuBuffer, offset, count, stride, true); +} + void GLES3PrimaryCommandBuffer::draw(const DrawInfo &info) { CC_PROFILE(GLES3PrimaryCommandBufferDraw); if (_isStateInvalid) { @@ -165,6 +185,13 @@ void GLES3PrimaryCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTex cmdFuncGLES3BlitTexture(GLES3Device::getInstance(), gpuTextureSrc, gpuTextureDst, blitRegions.data(), count, Filter::POINT); } +void GLES3PrimaryCommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + GLES3GPUBuffer *srcGLBuffer = static_cast(srcBuffer)->gpuBuffer(); + GLES3GPUBuffer *dstGLBuffer = static_cast(dstBuffer)->gpuBuffer(); + + cmdFuncGLES3CopyBuffer(srcGLBuffer, dstGLBuffer, regions, count); +} + void GLES3PrimaryCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { GLES3GPUTexture *gpuTextureSrc = nullptr; GLES3GPUTexture *gpuTextureDst = nullptr; diff --git a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h index 3ae09735302..5f2de6a58cd 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h +++ b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h @@ -40,6 +40,8 @@ class CC_GLES3_API GLES3PrimaryCommandBuffer final : public GLES3CommandBuffer { void endRenderPass() override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void setViewport(const Viewport &vp) override; void setScissor(const Rect &rect) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; @@ -50,6 +52,7 @@ class CC_GLES3_API GLES3PrimaryCommandBuffer final : public GLES3CommandBuffer { void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void beginQuery(QueryPool *queryPool, uint32_t id) override; void endQuery(QueryPool *queryPool, uint32_t id) override; void resetQueryPool(QueryPool *queryPool) override; diff --git a/native/cocos/renderer/gfx-metal/MTLBuffer.h b/native/cocos/renderer/gfx-metal/MTLBuffer.h index b214bedfc82..440eef050b4 100644 --- a/native/cocos/renderer/gfx-metal/MTLBuffer.h +++ b/native/cocos/renderer/gfx-metal/MTLBuffer.h @@ -54,8 +54,6 @@ class CCMTLBuffer final : public Buffer { inline CCMTLGPUBuffer *gpuBuffer() { return _gpuBuffer; } inline MTLIndexType getIndexType() const { return _indexType; } - inline bool isDrawIndirectByIndex() const { return _isDrawIndirectByIndex; } - inline const DrawInfoList &getDrawInfos() const { return _drawInfos; } protected: void doInit(const BufferInfo &info) override; @@ -72,11 +70,6 @@ class CCMTLBuffer final : public Buffer { uint32_t _bufferViewOffset = 0; uint8_t _lastUpdateCycle{0}; - bool _isDrawIndirectByIndex = false; - ccstd::vector _indexedPrimitivesIndirectArguments; - ccstd::vector _primitiveIndirectArguments; - DrawInfoList _drawInfos; - CCMTLGPUBuffer *_gpuBuffer = nullptr; }; diff --git a/native/cocos/renderer/gfx-metal/MTLBuffer.mm b/native/cocos/renderer/gfx-metal/MTLBuffer.mm index 9d36132a92e..1b1ec586fa1 100644 --- a/native/cocos/renderer/gfx-metal/MTLBuffer.mm +++ b/native/cocos/renderer/gfx-metal/MTLBuffer.mm @@ -69,16 +69,9 @@ of this software and associated engine source code (the "Software"), a limited, if (hasFlag(_usage, BufferUsageBit::VERTEX) || hasFlag(_usage, BufferUsageBit::UNIFORM) || hasFlag(_usage, BufferUsageBit::INDEX) || - hasFlag(_usage, BufferUsageBit::STORAGE)) { + hasFlag(_usage, BufferUsageBit::STORAGE) || + hasFlag(_usage, BufferUsageBit::INDIRECT)) { createMTLBuffer(_size, _memUsage); - } else if (hasFlag(_usage, BufferUsageBit::INDIRECT)) { - if (_isIndirectDrawSupported) { - createMTLBuffer(_size, _memUsage); - _primitiveIndirectArguments.resize(_count); - _indexedPrimitivesIndirectArguments.resize(_count); - } else { - _drawInfos.resize(_count); - } } CCMTLDevice::getInstance()->getMemoryStatus().bufferSize += _size; CC_PROFILE_MEMORY_INC(Buffer, _size); @@ -90,10 +83,6 @@ of this software and associated engine source code (the "Software"), a limited, _indexType = ccBuffer->getIndexType(); _mtlResourceOptions = ccBuffer->_mtlResourceOptions; _isIndirectDrawSupported = ccBuffer->_isIndirectDrawSupported; - _isDrawIndirectByIndex = ccBuffer->_isDrawIndirectByIndex; - _indexedPrimitivesIndirectArguments = ccBuffer->_indexedPrimitivesIndirectArguments; - _primitiveIndirectArguments = ccBuffer->_primitiveIndirectArguments; - _drawInfos = ccBuffer->_drawInfos; _bufferViewOffset = info.offset; _isBufferView = true; } @@ -143,18 +132,6 @@ of this software and associated engine source code (the "Software"), a limited, CCMTLDevice::getInstance()->getMemoryStatus().bufferSize -= _size; CC_PROFILE_MEMORY_DEC(Buffer, _size); - if (!_indexedPrimitivesIndirectArguments.empty()) { - _indexedPrimitivesIndirectArguments.clear(); - } - - if (!_primitiveIndirectArguments.empty()) { - _primitiveIndirectArguments.clear(); - } - - if (!_drawInfos.empty()) { - _drawInfos.clear(); - } - if (_gpuBuffer) { id mtlBuffer = _gpuBuffer->mtlBuffer; _gpuBuffer->mtlBuffer = nil; @@ -176,7 +153,8 @@ of this software and associated engine source code (the "Software"), a limited, void CCMTLBuffer::doResize(uint32_t size, uint32_t count) { if (hasFlag(_usage, BufferUsageBit::VERTEX) || hasFlag(_usage, BufferUsageBit::INDEX) || - hasFlag(_usage, BufferUsageBit::UNIFORM)) { + hasFlag(_usage, BufferUsageBit::UNIFORM) || + hasFlag(_usage, BufferUsageBit::INDIRECT)) { createMTLBuffer(size, _memUsage); } @@ -187,15 +165,6 @@ of this software and associated engine source code (the "Software"), a limited, _size = size; _count = count; - if (hasFlag(_usage, BufferUsageBit::INDIRECT)) { - if (_isIndirectDrawSupported) { - createMTLBuffer(size, _memUsage); - _primitiveIndirectArguments.resize(_count); - _indexedPrimitivesIndirectArguments.resize(_count); - } else { - _drawInfos.resize(_count); - } - } } void CCMTLBuffer::update(const void *buffer, uint32_t size) { @@ -205,52 +174,7 @@ of this software and associated engine source code (the "Software"), a limited, return; } - _isDrawIndirectByIndex = false; - - if (hasFlag(_usage, BufferUsageBit::INDIRECT)) { - uint32_t drawInfoCount = size / _stride; - const auto *drawInfo = static_cast(buffer); - if (drawInfoCount > 0) { - if (drawInfo->indexCount) { - _isDrawIndirectByIndex = true; - } - } - - if (_isIndirectDrawSupported) { - if (drawInfoCount > 0) { - if (_isDrawIndirectByIndex) { - uint32_t stride = sizeof(MTLDrawIndexedPrimitivesIndirectArguments); - - for (uint32_t i = 0; i < drawInfoCount; ++i) { - auto &arguments = _indexedPrimitivesIndirectArguments[i]; - arguments.indexCount = drawInfo->indexCount; - arguments.instanceCount = std::max(drawInfo->instanceCount, 1U); - arguments.indexStart = drawInfo->firstIndex; - arguments.baseVertex = drawInfo->firstVertex; - arguments.baseInstance = drawInfo->firstInstance; - ++drawInfo; - } - updateMTLBuffer(_indexedPrimitivesIndirectArguments.data(), 0, drawInfoCount * stride); - } else { - uint32_t stride = sizeof(MTLDrawPrimitivesIndirectArguments); - - for (uint32_t i = 0; i < drawInfoCount; ++i) { - auto &arguments = _primitiveIndirectArguments[i]; - arguments.vertexCount = drawInfo->vertexCount; - arguments.instanceCount = std::max(drawInfo->instanceCount, 1U); - arguments.vertexStart = drawInfo->firstVertex; - arguments.baseInstance = drawInfo->firstInstance; - ++drawInfo; - } - updateMTLBuffer(_primitiveIndirectArguments.data(), 0, drawInfoCount * stride); - } - } - } else { - memcpy(_drawInfos.data(), buffer, size); - } - } else { - updateMTLBuffer(buffer, 0, size); - } + updateMTLBuffer(buffer, 0, size); } void CCMTLBuffer::updateMTLBuffer(const void *buffer, uint32_t /*offset*/, uint32_t size) { diff --git a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h index bb38f1530cd..207e1ec74d7 100644 --- a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h +++ b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h @@ -69,11 +69,14 @@ class CCMTLCommandBuffer final : public CommandBuffer { void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override; @@ -96,6 +99,7 @@ class CCMTLCommandBuffer final : public CommandBuffer { void doInit(const CommandBufferInfo &info) override; void doDestroy() override; + void prepareForDraw(); void bindDescriptorSets(); void updateDepthStencilState(uint32_t subPassIndex, MTLRenderPassDescriptor *descriptor); static bool isRenderingEntireDrawable(const Rect &rect, const CCMTLFramebuffer *renderPass); diff --git a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm index 84cd6f958e0..484de3d365b 100644 --- a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm +++ b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm @@ -564,120 +564,96 @@ of this software and associated engine source code (the "Software"), a limited, } } -void CCMTLCommandBuffer::draw(const DrawInfo &info) { +void CCMTLCommandBuffer::prepareForDraw() { if(!_gpuCommandBufferObj->pipelineState || - !_gpuCommandBufferObj->pipelineState->getGPUPipelineState() || - !_gpuCommandBufferObj->pipelineState->getGPUPipelineState()->mtlRenderPipelineState) { + !_gpuCommandBufferObj->pipelineState->getGPUPipelineState() || + !_gpuCommandBufferObj->pipelineState->getGPUPipelineState()->mtlRenderPipelineState) { return; } - CC_PROFILE(CCMTLCommandBufferDraw); if (_firstDirtyDescriptorSet < _GPUDescriptorSets.size()) { bindDescriptorSets(); } +} + +void CCMTLCommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + prepareForDraw(); + auto mtlEncoder = _renderEncoder.getMTLEncoder(); + auto *mtlBuffer = static_cast(buffer); + for (uint32_t i = 0; i < count; ++i) { + const auto off = mtlBuffer->currentOffset() + offset + i * stride; + [mtlEncoder drawPrimitives: _mtlPrimitiveType + indirectBuffer: mtlBuffer->mtlBuffer() + indirectBufferOffset: off]; + } +} + +void CCMTLCommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + prepareForDraw(); + CCMTLInputAssembler *inputAssembler = _gpuCommandBufferObj->inputAssembler; + const auto *indexBuffer = static_cast(inputAssembler->getIndexBuffer()); + + auto mtlEncoder = _renderEncoder.getMTLEncoder(); + auto *mtlBuffer = static_cast(buffer); + for (uint32_t i = 0; i < count; ++i) { + const auto off = mtlBuffer->currentOffset() + offset + i * stride; + [mtlEncoder drawIndexedPrimitives: _mtlPrimitiveType + indexType: indexBuffer->getIndexType() + indexBuffer: indexBuffer->mtlBuffer() + indexBufferOffset: indexBuffer->currentOffset() + indirectBuffer: mtlBuffer->mtlBuffer() + indirectBufferOffset: off]; + } +} + +void CCMTLCommandBuffer::draw(const DrawInfo &info) { + CC_PROFILE(CCMTLCommandBufferDraw); + prepareForDraw(); CCMTLInputAssembler *inputAssembler = _gpuCommandBufferObj->inputAssembler; - const auto *indirectBuffer = static_cast(inputAssembler->getIndirectBuffer()); const auto *indexBuffer = static_cast(inputAssembler->getIndexBuffer()); auto mtlEncoder = _renderEncoder.getMTLEncoder(); - if (indirectBuffer) { - if (_indirectDrawSuppotred) { - ++_numDrawCalls; - if (indirectBuffer->isDrawIndirectByIndex()) { - [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType - indexType:indexBuffer->getIndexType() - indexBuffer:indexBuffer->mtlBuffer() - indexBufferOffset:indexBuffer->currentOffset() - indirectBuffer:indirectBuffer->mtlBuffer() - indirectBufferOffset:indirectBuffer->currentOffset()]; - } else { - [mtlEncoder drawPrimitives:_mtlPrimitiveType - indirectBuffer:indirectBuffer->mtlBuffer() - indirectBufferOffset:indirectBuffer->currentOffset()]; - } + if (info.indexCount > 0) { + uint32_t offset = 0; + offset += info.firstIndex * indexBuffer->getStride(); + if (info.instanceCount == 0) { + [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType + indexCount:info.indexCount + indexType:indexBuffer->getIndexType() + indexBuffer:indexBuffer->mtlBuffer() + indexBufferOffset:offset + indexBuffer->currentOffset()]; } else { - uint32_t stride = indirectBuffer->getStride(); - uint32_t offset = 0; - uint32_t drawInfoCount = indirectBuffer->getCount(); - const auto &drawInfos = indirectBuffer->getDrawInfos(); - _numDrawCalls += drawInfoCount; - - for (uint32_t i = 0; i < drawInfoCount; ++i) { - const auto &drawInfo = drawInfos[i]; - offset += drawInfo.firstIndex * stride; - if (indirectBuffer->isDrawIndirectByIndex()) { - if (drawInfo.instanceCount == 0) { - // indexbuffer offset: [backbuffer(triplebuffer maybe) offset] + [offset in this drawcall] - [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType - indexCount:drawInfo.indexCount - indexType:indexBuffer->getIndexType() - indexBuffer:indexBuffer->mtlBuffer() - indexBufferOffset:offset + indexBuffer->currentOffset()]; - } else { - [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType - indexCount:drawInfo.indexCount - indexType:indexBuffer->getIndexType() - indexBuffer:indexBuffer->mtlBuffer() - indexBufferOffset:offset + indexBuffer->currentOffset() - instanceCount:drawInfo.instanceCount]; - } - } else { - if (drawInfo.instanceCount == 0) { - [mtlEncoder drawPrimitives:_mtlPrimitiveType - vertexStart:drawInfo.firstVertex - vertexCount:drawInfo.vertexCount]; - } else { - [mtlEncoder drawPrimitives:_mtlPrimitiveType - vertexStart:drawInfo.firstVertex - vertexCount:drawInfo.vertexCount - instanceCount:drawInfo.instanceCount]; - } - } - } + [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType + indexCount:info.indexCount + indexType:indexBuffer->getIndexType() + indexBuffer:indexBuffer->mtlBuffer() + indexBufferOffset:offset + indexBuffer->currentOffset() + instanceCount:info.instanceCount]; } - } else { - if (info.indexCount > 0) { - uint32_t offset = 0; - offset += info.firstIndex * indexBuffer->getStride(); - if (info.instanceCount == 0) { - [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType - indexCount:info.indexCount - indexType:indexBuffer->getIndexType() - indexBuffer:indexBuffer->mtlBuffer() - indexBufferOffset:offset + indexBuffer->currentOffset()]; - } else { - [mtlEncoder drawIndexedPrimitives:_mtlPrimitiveType - indexCount:info.indexCount - indexType:indexBuffer->getIndexType() - indexBuffer:indexBuffer->mtlBuffer() - indexBufferOffset:offset + indexBuffer->currentOffset() - instanceCount:info.instanceCount]; - } - } else if (info.vertexCount) { - if (info.instanceCount == 0) { - [mtlEncoder drawPrimitives:_mtlPrimitiveType - vertexStart:info.firstVertex - vertexCount:info.vertexCount]; - } else { - [mtlEncoder drawPrimitives:_mtlPrimitiveType - vertexStart:info.firstVertex - vertexCount:info.vertexCount - instanceCount:info.instanceCount]; - } + } else if (info.vertexCount) { + if (info.instanceCount == 0) { + [mtlEncoder drawPrimitives:_mtlPrimitiveType + vertexStart:info.firstVertex + vertexCount:info.vertexCount]; + } else { + [mtlEncoder drawPrimitives:_mtlPrimitiveType + vertexStart:info.firstVertex + vertexCount:info.vertexCount + instanceCount:info.instanceCount]; } + } - _numInstances += info.instanceCount; - _numDrawCalls++; - if (_gpuCommandBufferObj->pipelineState) { - uint32_t indexCount = info.indexCount ? info.indexCount : info.vertexCount; - switch (_mtlPrimitiveType) { - case MTLPrimitiveTypeTriangle: - _numTriangles += indexCount / 3 * std::max(info.instanceCount, 1U); - break; - case MTLPrimitiveTypeTriangleStrip: - _numTriangles += (indexCount - 2) * std::max(info.instanceCount, 1U); - break; - default: break; - } + _numInstances += info.instanceCount; + _numDrawCalls++; + if (_gpuCommandBufferObj->pipelineState) { + uint32_t indexCount = info.indexCount ? info.indexCount : info.vertexCount; + switch (_mtlPrimitiveType) { + case MTLPrimitiveTypeTriangle: + _numTriangles += indexCount / 3 * std::max(info.instanceCount, 1U); + break; + case MTLPrimitiveTypeTriangleStrip: + _numTriangles += (indexCount - 2) * std::max(info.instanceCount, 1U); + break; + default: break; } } } @@ -933,6 +909,25 @@ of this software and associated engine source code (the "Software"), a limited, blitTexture(srcTexture, dstTexture, blitRegions.data(), count, Filter::POINT); } +void CCMTLCommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + id cmdBuffer = getMTLCommandBuffer(); + id encoder = [cmdBuffer blitCommandEncoder]; + + auto *ccSrcBuffer = static_cast(srcBuffer); + auto *ccDstBuffer = static_cast(dstBuffer); + + for (uint32_t i = 0; i < count; ++i) { + const auto © = regions[i]; + [encoder copyFromBuffer: ccSrcBuffer->mtlBuffer() + sourceOffset: ccSrcBuffer->currentOffset() + copy.srcOffset + toBuffer: ccDstBuffer->mtlBuffer() + destinationOffset: ccDstBuffer->currentOffset() + copy.dstOffset + size: copy.size]; + } + + [encoder endEncoding]; +} + void CCMTLCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { if (srcTexture && dstTexture && regions) { id cmdBuffer = getMTLCommandBuffer(); diff --git a/native/cocos/renderer/gfx-validator/BufferValidator.cpp b/native/cocos/renderer/gfx-validator/BufferValidator.cpp index a6e5f691b05..a2ed6d279cf 100644 --- a/native/cocos/renderer/gfx-validator/BufferValidator.cpp +++ b/native/cocos/renderer/gfx-validator/BufferValidator.cpp @@ -145,18 +145,6 @@ void BufferValidator::update(const void *buffer, uint32_t size) { CC_ASSERT(size && size <= _size); CC_ASSERT(buffer); - if (hasFlag(_usage, BufferUsageBit::INDIRECT)) { - const auto *drawInfo = static_cast(buffer); - const size_t drawInfoCount = size / sizeof(DrawInfo); - const bool isIndexed = drawInfoCount > 0 && drawInfo->indexCount > 0; - for (size_t i = 1U; i < drawInfoCount; ++i) { - if ((++drawInfo)->indexCount > 0 != isIndexed) { - // Inconsistent indirect draw infos on using index buffer. - CC_ABORT(); - } - } - } - sanityCheck(buffer, size); ++_totalUpdateTimes; // only count direct updates diff --git a/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp b/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp index bab7e3c6ca5..3b584ca7cb0 100644 --- a/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp +++ b/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp @@ -384,6 +384,32 @@ void CommandBufferValidator::draw(const DrawInfo &info) { _actor->draw(info); } +void CommandBufferValidator::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) +{ + CC_ASSERT(stride == (sizeof(DrawIndirectCommand))); + CC_ASSERT(isInited()); + CC_ASSERT(buffer); + CC_ASSERT(hasFlag(buffer->getUsage(), BufferUsageBit::INDIRECT)); + + auto *bufferValidator = static_cast(buffer); + CC_ASSERT(bufferValidator->isInited()); + + _actor->drawIndirect(bufferValidator->getActor(), offset, count, stride); +} + +void CommandBufferValidator::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) +{ + CC_ASSERT(stride == (sizeof(DrawIndexedIndirectCommand))); + CC_ASSERT(isInited()); + CC_ASSERT(buffer); + CC_ASSERT(hasFlag(buffer->getUsage(), BufferUsageBit::INDIRECT)); + + auto *bufferValidator = static_cast(buffer); + CC_ASSERT(bufferValidator->isInited()); + + _actor->drawIndexedIndirect(bufferValidator->getActor(), offset, count, stride); +} + void CommandBufferValidator::updateBuffer(Buffer *buff, const void *data, uint32_t size) { CC_ASSERT(isInited()); CC_ASSERT(buff && static_cast(buff)->isInited()); @@ -483,6 +509,31 @@ void CommandBufferValidator::copyTexture(Texture *srcTexture, Texture *dstTextur _actor->copyTexture(actorSrcTexture, actorDstTexture, regions, count); } +void CommandBufferValidator::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + CC_ASSERT(isInited()); + CC_ASSERT(srcBuffer && static_cast(srcBuffer)->isInited()); + CC_ASSERT(dstBuffer && static_cast(dstBuffer)->isInited()); + const auto &srcSize = dstBuffer->getSize(); + const auto &dstSize = srcBuffer->getSize(); + + CC_ASSERT(!_insideRenderPass); + + for (uint32_t i = 0; i < count; ++i) { + const auto ®ion = regions[i]; + CC_ASSERT(region.srcOffset + region.size <= srcSize); + CC_ASSERT(region.dstOffset + region.size <= dstSize); + } + + /////////// execute /////////// + + Buffer *actorSrcBuffer = nullptr; + Buffer *actorDstBuffer = nullptr; + if (srcBuffer) actorSrcBuffer = static_cast(srcBuffer)->getActor(); + if (dstBuffer) actorDstBuffer = static_cast(dstBuffer)->getActor(); + + _actor->copyBuffer(actorSrcBuffer, actorDstBuffer, regions, count); +} + void CommandBufferValidator::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { CC_ASSERT(isInited()); CC_ASSERT(srcTexture && static_cast(srcTexture)->isInited()); diff --git a/native/cocos/renderer/gfx-validator/CommandBufferValidator.h b/native/cocos/renderer/gfx-validator/CommandBufferValidator.h index 3ec70240be2..264f3539aa3 100644 --- a/native/cocos/renderer/gfx-validator/CommandBufferValidator.h +++ b/native/cocos/renderer/gfx-validator/CommandBufferValidator.h @@ -54,11 +54,14 @@ class CC_DLL CommandBufferValidator final : public Agent { void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buff, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override; diff --git a/native/cocos/renderer/gfx-validator/InputAssemblerValidator.cpp b/native/cocos/renderer/gfx-validator/InputAssemblerValidator.cpp index 8b76576de31..f6b104ac014 100644 --- a/native/cocos/renderer/gfx-validator/InputAssemblerValidator.cpp +++ b/native/cocos/renderer/gfx-validator/InputAssemblerValidator.cpp @@ -60,10 +60,6 @@ void InputAssemblerValidator::doInit(const InputAssemblerInfo &info) { CC_ASSERT(static_cast(info.indexBuffer)->isInited()); CC_ASSERT(hasFlag(info.indexBuffer->getUsage(), BufferUsageBit::INDEX)); } - if (info.indirectBuffer) { - CC_ASSERT(static_cast(info.indirectBuffer)->isInited()); - CC_ASSERT(hasFlag(info.indirectBuffer->getUsage(), BufferUsageBit::INDIRECT)); - } /////////// execute /////////// @@ -74,9 +70,6 @@ void InputAssemblerValidator::doInit(const InputAssemblerInfo &info) { if (actorInfo.indexBuffer) { actorInfo.indexBuffer = static_cast(actorInfo.indexBuffer)->getActor(); } - if (actorInfo.indirectBuffer) { - actorInfo.indirectBuffer = static_cast(actorInfo.indirectBuffer)->getActor(); - } _actor->initialize(actorInfo); } diff --git a/native/cocos/renderer/gfx-vulkan/VKBuffer.cpp b/native/cocos/renderer/gfx-vulkan/VKBuffer.cpp index 63f4e1e114d..620523b0bf0 100644 --- a/native/cocos/renderer/gfx-vulkan/VKBuffer.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKBuffer.cpp @@ -101,12 +101,6 @@ void CCVKGPUBuffer::shutdown() { } void CCVKGPUBuffer::init() { - if (hasFlag(usage, BufferUsageBit::INDIRECT)) { - const size_t drawInfoCount = size / sizeof(DrawInfo); - indexedIndirectCmds.resize(drawInfoCount); - indirectCmds.resize(drawInfoCount); - } - cmdFuncCCVKCreateBuffer(CCVKDevice::getInstance(), this); CCVKDevice::getInstance()->getMemoryStatus().bufferSize += size; CC_PROFILE_MEMORY_INC(Buffer, size); diff --git a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp index 7aefa9312fc..6fe3dcd0e27 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp @@ -408,77 +408,94 @@ void CCVKCommandBuffer::nextSubpass() { _hasSubPassSelfDependency = _curGPURenderPass->hasSelfDependency[_currentSubPass]; } -void CCVKCommandBuffer::draw(const DrawInfo &info) { - CC_PROFILE(CCVKCmdBufDraw); +void CCVKCommandBuffer::drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { if (_firstDirtyDescriptorSet < _curGPUDescriptorSets.size()) { bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS); } - const auto *gpuIndirectBuffer = _curGPUInputAssembler->gpuIndirectBuffer.get(); + auto *vkBuffer = static_cast(buffer); + auto *gpuBuffer = vkBuffer->gpuBufferView(); - if (gpuIndirectBuffer) { - uint32_t drawInfoCount = gpuIndirectBuffer->range / gpuIndirectBuffer->gpuBuffer->stride; - CCVKGPUDevice *gpuDevice = CCVKDevice::getInstance()->gpuDevice(); - VkDeviceSize offset = gpuIndirectBuffer->getStartOffset(gpuDevice->curBackBufferIndex); - if (gpuDevice->useMultiDrawIndirect) { - if (gpuIndirectBuffer->gpuBuffer->isDrawIndirectByIndex) { - vkCmdDrawIndexedIndirect(_gpuCommandBuffer->vkCommandBuffer, - gpuIndirectBuffer->gpuBuffer->vkBuffer, - offset, - drawInfoCount, - sizeof(VkDrawIndexedIndirectCommand)); - } else { - vkCmdDrawIndirect(_gpuCommandBuffer->vkCommandBuffer, - gpuIndirectBuffer->gpuBuffer->vkBuffer, - offset, - drawInfoCount, - sizeof(VkDrawIndirectCommand)); - } - } else { - if (gpuIndirectBuffer->gpuBuffer->isDrawIndirectByIndex) { - for (VkDeviceSize j = 0U; j < drawInfoCount; ++j) { - vkCmdDrawIndexedIndirect(_gpuCommandBuffer->vkCommandBuffer, - gpuIndirectBuffer->gpuBuffer->vkBuffer, - offset + j * sizeof(VkDrawIndexedIndirectCommand), - 1, - sizeof(VkDrawIndexedIndirectCommand)); - } - } else { - for (VkDeviceSize j = 0U; j < drawInfoCount; ++j) { - vkCmdDrawIndirect(_gpuCommandBuffer->vkCommandBuffer, - gpuIndirectBuffer->gpuBuffer->vkBuffer, - offset + j * sizeof(VkDrawIndirectCommand), - 1, - sizeof(VkDrawIndirectCommand)); - } - } - } + CCVKGPUDevice *gpuDevice = CCVKDevice::getInstance()->gpuDevice(); + uint32_t bufferOffset = gpuBuffer->getStartOffset(gpuDevice->curBackBufferIndex); + + if (gpuDevice->useMultiDrawIndirect) { + vkCmdDrawIndirect(_gpuCommandBuffer->vkCommandBuffer, + vkBuffer->gpuBuffer()->vkBuffer, + bufferOffset + offset, + count, + stride); } else { - uint32_t instanceCount = std::max(info.instanceCount, 1U); - bool hasIndexBuffer = _curGPUInputAssembler->gpuIndexBuffer && info.indexCount > 0; + for (uint32_t i = 0U; i < count; ++i) { + uint32_t currentOffset = bufferOffset + offset + i * stride; + vkCmdDrawIndirect(_gpuCommandBuffer->vkCommandBuffer, + vkBuffer->gpuBuffer()->vkBuffer, + currentOffset, + 1, + stride); + } + } +} - if (hasIndexBuffer) { - vkCmdDrawIndexed(_gpuCommandBuffer->vkCommandBuffer, info.indexCount, instanceCount, - info.firstIndex, info.vertexOffset, info.firstInstance); - } else { - vkCmdDraw(_gpuCommandBuffer->vkCommandBuffer, info.vertexCount, instanceCount, - info.firstVertex, info.firstInstance); +void CCVKCommandBuffer::drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) { + if (_firstDirtyDescriptorSet < _curGPUDescriptorSets.size()) { + bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS); + } + + auto *vkBuffer = static_cast(buffer); + auto *gpuBuffer = vkBuffer->gpuBufferView(); + + CCVKGPUDevice *gpuDevice = CCVKDevice::getInstance()->gpuDevice(); + uint32_t bufferOffset = gpuBuffer->getStartOffset(gpuDevice->curBackBufferIndex); + + if (gpuDevice->useMultiDrawIndirect) { + vkCmdDrawIndexedIndirect(_gpuCommandBuffer->vkCommandBuffer, + vkBuffer->gpuBuffer()->vkBuffer, + bufferOffset + offset, + count, + stride); + } else { + for (uint32_t i = 0U; i < count; ++i) { + uint32_t currentOffset = bufferOffset + offset + i * stride; + vkCmdDrawIndexedIndirect(_gpuCommandBuffer->vkCommandBuffer, + vkBuffer->gpuBuffer()->vkBuffer, + currentOffset, + 1, + stride); } + } +} - ++_numDrawCalls; - _numInstances += info.instanceCount; - if (_curGPUPipelineState) { - uint32_t indexCount = hasIndexBuffer ? info.indexCount : info.vertexCount; - switch (_curGPUPipelineState->primitive) { - case PrimitiveMode::TRIANGLE_LIST: - _numTriangles += indexCount / 3 * instanceCount; - break; - case PrimitiveMode::TRIANGLE_STRIP: - case PrimitiveMode::TRIANGLE_FAN: - _numTriangles += (indexCount - 2) * instanceCount; - break; - default: break; - } +void CCVKCommandBuffer::draw(const DrawInfo &info) { + CC_PROFILE(CCVKCmdBufDraw); + if (_firstDirtyDescriptorSet < _curGPUDescriptorSets.size()) { + bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS); + } + + uint32_t instanceCount = std::max(info.instanceCount, 1U); + bool hasIndexBuffer = _curGPUInputAssembler->gpuIndexBuffer && info.indexCount > 0; + + if (hasIndexBuffer) { + vkCmdDrawIndexed(_gpuCommandBuffer->vkCommandBuffer, info.indexCount, instanceCount, + info.firstIndex, info.vertexOffset, info.firstInstance); + } else { + vkCmdDraw(_gpuCommandBuffer->vkCommandBuffer, info.vertexCount, instanceCount, + info.firstVertex, info.firstInstance); + } + + ++_numDrawCalls; + _numInstances += info.instanceCount; + if (_curGPUPipelineState) { + uint32_t indexCount = hasIndexBuffer ? info.indexCount : info.vertexCount; + switch (_curGPUPipelineState->primitive) { + case PrimitiveMode::TRIANGLE_LIST: + _numTriangles += indexCount / 3 * instanceCount; + break; + case PrimitiveMode::TRIANGLE_STRIP: + case PrimitiveMode::TRIANGLE_FAN: + _numTriangles += (indexCount - 2) * instanceCount; + break; + default: break; } } if (_hasSubPassSelfDependency) { @@ -606,6 +623,22 @@ void CCVKCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, co vkCmdCopyImage(_gpuCommandBuffer->vkCommandBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, count, copyRegions.data()); } +void CCVKCommandBuffer::copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) { + CCVKGPUBuffer *gpuSrcBuffer = static_cast(srcBuffer)->gpuBuffer(); + CCVKGPUBuffer *gpuDstBuffer = static_cast(dstBuffer)->gpuBuffer(); + + ccstd::vector copyRegions(count, VkBufferCopy{}); + for (uint32_t i = 0U; i < count; ++i) { + const BufferCopy ®ion = regions[i]; + auto ©Region = copyRegions[i]; + + copyRegion.srcOffset = static_cast(region.srcOffset); + copyRegion.dstOffset = static_cast(region.dstOffset); + copyRegion.size = static_cast(region.size); + } + vkCmdCopyBuffer(_gpuCommandBuffer->vkCommandBuffer, gpuSrcBuffer->vkBuffer, gpuDstBuffer->vkBuffer, count, copyRegions.data()); +} + void CCVKCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { VkImageAspectFlags srcAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; VkImageAspectFlags dstAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; diff --git a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h index 1eae85158ed..16a5fb333e9 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h +++ b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h @@ -54,11 +54,14 @@ class CC_VULKAN_API CCVKCommandBuffer final : public CommandBuffer { void setStencilCompareMask(StencilFace face, uint32_t reference, uint32_t mask) override; void nextSubpass() override; void draw(const DrawInfo &info) override; + void drawIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; + void drawIndexedIndirect(Buffer *buffer, uint32_t offset, uint32_t count, uint32_t stride) override; void updateBuffer(Buffer *buffer, const void *data, uint32_t size) override; void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override; void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override; void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; + void copyBuffer(Buffer *srcBuffer, Buffer *dstBuffer, const BufferCopy *regions, uint32_t count) override; void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override; diff --git a/native/cocos/renderer/gfx-vulkan/VKCommands.cpp b/native/cocos/renderer/gfx-vulkan/VKCommands.cpp index cf098298382..65b139effa4 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommands.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKCommands.cpp @@ -1208,42 +1208,8 @@ void bufferUpload(const CCVKGPUBufferView &stagingBuffer, CCVKGPUBuffer &gpuBuff void cmdFuncCCVKUpdateBuffer(CCVKDevice *device, CCVKGPUBuffer *gpuBuffer, const void *buffer, uint32_t size, const CCVKGPUCommandBuffer *cmdBuffer) { if (!gpuBuffer) return; - const void *dataToUpload = nullptr; - size_t sizeToUpload = 0U; - - if (hasFlag(gpuBuffer->usage, BufferUsageBit::INDIRECT)) { - size_t drawInfoCount = size / sizeof(DrawInfo); - const auto *drawInfo = static_cast(buffer); - if (drawInfoCount > 0) { - if (drawInfo->indexCount) { - for (size_t i = 0; i < drawInfoCount; ++i) { - gpuBuffer->indexedIndirectCmds[i].indexCount = drawInfo->indexCount; - gpuBuffer->indexedIndirectCmds[i].instanceCount = std::max(drawInfo->instanceCount, 1U); - gpuBuffer->indexedIndirectCmds[i].firstIndex = drawInfo->firstIndex; - gpuBuffer->indexedIndirectCmds[i].vertexOffset = drawInfo->vertexOffset; - gpuBuffer->indexedIndirectCmds[i].firstInstance = drawInfo->firstInstance; - drawInfo++; - } - dataToUpload = gpuBuffer->indexedIndirectCmds.data(); - sizeToUpload = drawInfoCount * sizeof(VkDrawIndexedIndirectCommand); - gpuBuffer->isDrawIndirectByIndex = true; - } else { - for (size_t i = 0; i < drawInfoCount; ++i) { - gpuBuffer->indirectCmds[i].vertexCount = drawInfo->vertexCount; - gpuBuffer->indirectCmds[i].instanceCount = std::max(drawInfo->instanceCount, 1U); - gpuBuffer->indirectCmds[i].firstVertex = drawInfo->firstVertex; - gpuBuffer->indirectCmds[i].firstInstance = drawInfo->firstInstance; - drawInfo++; - } - dataToUpload = gpuBuffer->indirectCmds.data(); - sizeToUpload = drawInfoCount * sizeof(VkDrawIndirectCommand); - gpuBuffer->isDrawIndirectByIndex = false; - } - } - } else { - dataToUpload = buffer; - sizeToUpload = size; - } + const void *dataToUpload = buffer; + size_t sizeToUpload = size; // back buffer instances update command uint32_t backBufferIndex = device->gpuDevice()->curBackBufferIndex; diff --git a/native/cocos/renderer/gfx-vulkan/VKDevice.cpp b/native/cocos/renderer/gfx-vulkan/VKDevice.cpp index 85d9bacdfcb..3dc767fa6eb 100644 --- a/native/cocos/renderer/gfx-vulkan/VKDevice.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKDevice.cpp @@ -821,6 +821,8 @@ void CCVKDevice::initExtensionCapability() { _caps.supportVariableRateShading &= hasFlag(_formatFeatures[static_cast(Format::R8UI)], FormatFeatureBit::SHADING_RATE); _caps.supportSubPassShading = checkExtension(VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME); + _caps.supportMultiDrawIndirect = _gpuContext->physicalDeviceFeatures.multiDrawIndirect && + _gpuContext->physicalDeviceFeatures.drawIndirectFirstInstance; } CommandBuffer *CCVKDevice::createCommandBuffer(const CommandBufferInfo & /*info*/, bool /*hasAgent*/) { diff --git a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h index cb386223c67..22e3551a32c 100644 --- a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h +++ b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h @@ -222,10 +222,6 @@ struct CCVKGPUBuffer : public CCVKGPUDeviceObject { uint32_t count = 0U; void *buffer = nullptr; - bool isDrawIndirectByIndex = false; - ccstd::vector indirectCmds; - ccstd::vector indexedIndirectCmds; - uint8_t *mappedData = nullptr; VmaAllocation vmaAllocation = VK_NULL_HANDLE; @@ -341,7 +337,6 @@ struct CCVKGPUInputAssembler : public CCVKGPUDeviceObject { AttributeList attributes; ccstd::vector> gpuVertexBuffers; ConstPtr gpuIndexBuffer; - ConstPtr gpuIndirectBuffer; ccstd::vector vertexBuffers; ccstd::vector vertexBufferOffsets; }; diff --git a/native/cocos/renderer/gfx-vulkan/VKInputAssembler.cpp b/native/cocos/renderer/gfx-vulkan/VKInputAssembler.cpp index f7dae717a66..6b1f5a1b638 100644 --- a/native/cocos/renderer/gfx-vulkan/VKInputAssembler.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKInputAssembler.cpp @@ -57,11 +57,6 @@ void CCVKInputAssembler::doInit(const InputAssemblerInfo &info) { hub->connect(_gpuInputAssembler, _gpuInputAssembler->gpuIndexBuffer.get()); } - if (info.indirectBuffer) { - _gpuInputAssembler->gpuIndirectBuffer = static_cast(info.indirectBuffer)->gpuBufferView(); - hub->connect(_gpuInputAssembler, _gpuInputAssembler->gpuIndirectBuffer.get()); - } - _gpuInputAssembler->vertexBuffers.resize(vbCount); _gpuInputAssembler->vertexBufferOffsets.resize(vbCount); @@ -84,9 +79,6 @@ void CCVKGPUInputAssembler::shutdown() { if (gpuIndexBuffer) { hub->disengage(this, gpuIndexBuffer); } - if (gpuIndirectBuffer) { - hub->disengage(this, gpuIndirectBuffer); - } } void CCVKGPUInputAssembler::update(const CCVKGPUBufferView *oldBuffer, const CCVKGPUBufferView *newBuffer) { @@ -99,9 +91,6 @@ void CCVKGPUInputAssembler::update(const CCVKGPUBufferView *oldBuffer, const CCV if (gpuIndexBuffer.get() == oldBuffer) { gpuIndexBuffer = newBuffer; } - if (gpuIndirectBuffer.get() == oldBuffer) { - gpuIndirectBuffer = newBuffer; - } } } // namespace gfx diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 23fdda466bc..c931a76bc52 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -1441,10 +1441,23 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { const CopyPair& copy, ResourceGraph::vertex_descriptor srcID, ResourceGraph::vertex_descriptor dstID) const { - // TODO(zhouzhenglong): add impl - std::ignore = copy; - std::ignore = srcID; - std::ignore = dstID; + auto& resg = ctx.resourceGraph; + std::vector copyInfos(1, gfx::BufferCopy{}); + + gfx::Buffer* srcBuffer = resg.getBuffer(srcID); + gfx::Buffer* dstBuffer = resg.getBuffer(dstID); + CC_ENSURES(srcBuffer); + CC_ENSURES(dstBuffer); + if (!srcBuffer || !dstBuffer) { + return; + } + + auto& copyInfo = copyInfos[0]; + copyInfo.srcOffset = copy.sourceOffset; + copyInfo.dstOffset = copy.targetOffset; + copyInfo.size = copy.bufferSize; + + ctx.cmdBuff->copyBuffer(srcBuffer, dstBuffer, copyInfos.data(), 1); } void uploadTexture( // NOLINT(readability-convert-member-functions-to-static) const UploadPair& upload, diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h index 846d97ac32d..b059e3fd307 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineFwd.h @@ -50,6 +50,7 @@ class NativeMultisampleRenderPassBuilder; class NativeComputeQueueBuilder; class NativeComputePassBuilder; struct RenderInstancingQueue; +struct RenderBatchingQueue; struct DrawInstance; struct RenderDrawQueue; struct NativeRenderQueue; diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.cpp index d8de417ef46..dca32301121 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) {} +RenderBatchingQueue::RenderBatchingQueue(const allocator_type& alloc) noexcept +: batches(alloc) {} + +RenderBatchingQueue::RenderBatchingQueue(RenderBatchingQueue&& rhs, const allocator_type& alloc) +: batches(std::move(rhs.batches), alloc) {} + +RenderBatchingQueue::RenderBatchingQueue(RenderBatchingQueue const& rhs, const allocator_type& alloc) +: batches(rhs.batches, alloc) {} + RenderDrawQueue::RenderDrawQueue(const allocator_type& alloc) noexcept : instances(alloc) {} @@ -62,13 +71,17 @@ NativeRenderQueue::NativeRenderQueue(const allocator_type& alloc) noexcept : opaqueQueue(alloc), transparentQueue(alloc), opaqueInstancingQueue(alloc), - transparentInstancingQueue(alloc) {} + transparentInstancingQueue(alloc), + opaqueBatchingQueue(alloc), + transparentBatchingQueue(alloc) {} NativeRenderQueue::NativeRenderQueue(SceneFlags sceneFlagsIn, uint32_t subpassOrPassLayoutIDIn, const allocator_type& alloc) noexcept : opaqueQueue(alloc), transparentQueue(alloc), opaqueInstancingQueue(alloc), transparentInstancingQueue(alloc), + opaqueBatchingQueue(alloc), + transparentBatchingQueue(alloc), sceneFlags(sceneFlagsIn), subpassOrPassLayoutID(subpassOrPassLayoutIDIn) {} @@ -77,6 +90,8 @@ NativeRenderQueue::NativeRenderQueue(NativeRenderQueue&& rhs, const allocator_ty transparentQueue(std::move(rhs.transparentQueue), alloc), opaqueInstancingQueue(std::move(rhs.opaqueInstancingQueue), alloc), transparentInstancingQueue(std::move(rhs.transparentInstancingQueue), alloc), + opaqueBatchingQueue(std::move(rhs.opaqueBatchingQueue), alloc), + transparentBatchingQueue(std::move(rhs.transparentBatchingQueue), alloc), sceneFlags(rhs.sceneFlags), subpassOrPassLayoutID(rhs.subpassOrPassLayoutID) {} diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index b21235bc46b..87d1282869d 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -796,6 +796,27 @@ struct RenderInstancingQueue { ccstd::pmr::vector> instanceBuffers; }; +struct RenderBatchingQueue { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {batches.get_allocator().resource()}; + } + + RenderBatchingQueue(const allocator_type& alloc) noexcept; // NOLINT + RenderBatchingQueue(RenderBatchingQueue&& rhs, const allocator_type& alloc); + RenderBatchingQueue(RenderBatchingQueue const& rhs, const allocator_type& alloc); + + RenderBatchingQueue(RenderBatchingQueue&& rhs) noexcept = default; + RenderBatchingQueue(RenderBatchingQueue const& rhs) = delete; + RenderBatchingQueue& operator=(RenderBatchingQueue&& rhs) = default; + RenderBatchingQueue& operator=(RenderBatchingQueue const& rhs) = default; + + static void recordCommandBuffer(gfx::Device *device, const scene::Camera *camera, + gfx::RenderPass *renderPass, gfx::CommandBuffer *cmdBuffer, SceneFlags sceneFlags); + + ccstd::pmr::vector batches; +}; + struct DrawInstance { const scene::SubModel* subModel{nullptr}; uint32_t priority{0}; @@ -853,6 +874,8 @@ struct NativeRenderQueue { RenderDrawQueue transparentQueue; RenderInstancingQueue opaqueInstancingQueue; RenderInstancingQueue transparentInstancingQueue; + RenderBatchingQueue opaqueBatchingQueue; + RenderBatchingQueue transparentBatchingQueue; SceneFlags sceneFlags{SceneFlags::NONE}; uint32_t subpassOrPassLayoutID{0xFFFFFFFF}; }; diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp index 9bb23563b0b..b60875af911 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp @@ -165,6 +165,15 @@ bool nativevalue_to_se(const cc::render::CopyPair &from, se::Value &to, se::Obje nativevalue_to_se(from.targetPlaneSlice, tmp, ctx); obj->setProperty("targetPlaneSlice", tmp); + nativevalue_to_se(from.sourceOffset, tmp, ctx); + obj->setProperty("sourceOffset", tmp); + + nativevalue_to_se(from.targetOffset, tmp, ctx); + obj->setProperty("targetOffset", tmp); + + nativevalue_to_se(from.bufferSize, tmp, ctx); + obj->setProperty("bufferSize", tmp); + to.setObject(obj); return true; } @@ -400,6 +409,18 @@ bool sevalue_to_native(const se::Value &from, cc::render:: if(!field.isNullOrUndefined()) { ok &= sevalue_to_native(field, &(to->targetPlaneSlice), ctx); } + obj->getProperty("sourceOffset", &field, true); + if(!field.isNullOrUndefined()) { + ok &= sevalue_to_native(field, &(to->sourceOffset), ctx); + } + obj->getProperty("targetOffset", &field, true); + if(!field.isNullOrUndefined()) { + ok &= sevalue_to_native(field, &(to->targetOffset), ctx); + } + obj->getProperty("bufferSize", &field, true); + if(!field.isNullOrUndefined()) { + ok &= sevalue_to_native(field, &(to->bufferSize), ctx); + } return ok; } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h index 49fa456c4cd..070eef8a9f8 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h @@ -130,6 +130,9 @@ inline void save(OutputArchive& ar, const CopyPair& v) { save(ar, v.targetMostDetailedMip); save(ar, v.targetFirstSlice); save(ar, v.targetPlaneSlice); + save(ar, v.sourceOffset); + save(ar, v.targetOffset); + save(ar, v.bufferSize); } inline void load(InputArchive& ar, CopyPair& v) { @@ -143,6 +146,9 @@ inline void load(InputArchive& ar, CopyPair& v) { load(ar, v.targetMostDetailedMip); load(ar, v.targetFirstSlice); load(ar, v.targetPlaneSlice); + load(ar, v.sourceOffset); + load(ar, v.targetOffset); + load(ar, v.bufferSize); } inline void save(OutputArchive& ar, const MovePair& v) { diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.cpp index 1f556cf1058..ad6ef4ed792 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.cpp @@ -75,6 +75,13 @@ CopyPair::CopyPair(ccstd::pmr::string sourceIn, ccstd::pmr::string targetIn, uin targetFirstSlice(targetFirstSliceIn), targetPlaneSlice(targetPlaneSliceIn) {} +CopyPair::CopyPair(ccstd::pmr::string sourceIn, ccstd::pmr::string targetIn, uint32_t sourceOffsetIn, uint32_t targetOffsetIn, uint32_t bufferSizeIn, const allocator_type& alloc) noexcept // NOLINT +: source(std::move(sourceIn), alloc), + target(std::move(targetIn), alloc), + sourceOffset(sourceOffsetIn), + targetOffset(targetOffsetIn), + bufferSize(bufferSizeIn) {} + CopyPair::CopyPair(CopyPair&& rhs, const allocator_type& alloc) : source(std::move(rhs.source), alloc), target(std::move(rhs.target), alloc), @@ -85,7 +92,10 @@ CopyPair::CopyPair(CopyPair&& rhs, const allocator_type& alloc) sourcePlaneSlice(rhs.sourcePlaneSlice), targetMostDetailedMip(rhs.targetMostDetailedMip), targetFirstSlice(rhs.targetFirstSlice), - targetPlaneSlice(rhs.targetPlaneSlice) {} + targetPlaneSlice(rhs.targetPlaneSlice), + sourceOffset(rhs.sourceOffset), + targetOffset(rhs.targetOffset), + bufferSize(rhs.bufferSize) {} CopyPair::CopyPair(CopyPair const& rhs, const allocator_type& alloc) : source(rhs.source, alloc), @@ -97,7 +107,10 @@ CopyPair::CopyPair(CopyPair const& rhs, const allocator_type& alloc) sourcePlaneSlice(rhs.sourcePlaneSlice), targetMostDetailedMip(rhs.targetMostDetailedMip), targetFirstSlice(rhs.targetFirstSlice), - targetPlaneSlice(rhs.targetPlaneSlice) {} + targetPlaneSlice(rhs.targetPlaneSlice), + sourceOffset(rhs.sourceOffset), + targetOffset(rhs.targetOffset), + bufferSize(rhs.bufferSize) {} UploadPair::UploadPair(const allocator_type& alloc) noexcept : target(alloc) {} diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index eb6dfe6a9b3..c17fe2c50c7 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -346,6 +346,7 @@ struct CopyPair { CopyPair(const allocator_type& alloc = boost::container::pmr::get_default_resource()) noexcept; // NOLINT CopyPair(ccstd::pmr::string sourceIn, ccstd::pmr::string targetIn, uint32_t mipLevelsIn, uint32_t numSlicesIn, uint32_t sourceMostDetailedMipIn, uint32_t sourceFirstSliceIn, uint32_t sourcePlaneSliceIn, uint32_t targetMostDetailedMipIn, uint32_t targetFirstSliceIn, uint32_t targetPlaneSliceIn, const allocator_type& alloc = boost::container::pmr::get_default_resource()) noexcept; + CopyPair(ccstd::pmr::string sourceIn, ccstd::pmr::string targetIn, uint32_t sourceOffsetIn, uint32_t targetOffsetIn, uint32_t bufferSizeIn, const allocator_type& alloc = boost::container::pmr::get_default_resource()) noexcept; CopyPair(CopyPair&& rhs, const allocator_type& alloc); CopyPair(CopyPair const& rhs, const allocator_type& alloc); @@ -364,6 +365,9 @@ struct CopyPair { uint32_t targetMostDetailedMip{0}; uint32_t targetFirstSlice{0}; uint32_t targetPlaneSlice{0}; + uint32_t sourceOffset{0}; + uint32_t targetOffset{0}; + uint32_t bufferSize{0}; }; struct UploadPair { diff --git a/native/cocos/renderer/pipeline/xr/ar/ARBackground.cpp b/native/cocos/renderer/pipeline/xr/ar/ARBackground.cpp index 137ca304310..130554450af 100644 --- a/native/cocos/renderer/pipeline/xr/ar/ARBackground.cpp +++ b/native/cocos/renderer/pipeline/xr/ar/ARBackground.cpp @@ -201,22 +201,10 @@ void ARBackground::activate(RenderPipeline *pipeline, gfx::Device *dev) { auto *indexBuffer = _device->createBuffer(indexBufferInfo); indexBuffer->update(indices, sizeof(indices)); - gfx::DrawInfo drawInfo; - drawInfo.indexCount = 6; - gfx::BufferInfo indirectBufferInfo = { - gfx::BufferUsageBit::INDIRECT, - gfx::MemoryUsage::DEVICE, - sizeof(gfx::DrawInfo), - sizeof(gfx::DrawInfo), - }; - auto *indirectBuffer = _device->createBuffer(indirectBufferInfo); - indirectBuffer->update(&drawInfo, sizeof(gfx::DrawInfo)); - - gfx::InputAssemblerInfo inputAssemblerInfo; + gfx::InputAssemblerInfo inputAssemblerInfo = {}; inputAssemblerInfo.attributes = std::move(attributeList); inputAssemblerInfo.vertexBuffers.emplace_back(_vertexBuffer); inputAssemblerInfo.indexBuffer = indexBuffer; - inputAssemblerInfo.indirectBuffer = indirectBuffer; _inputAssembler = _device->createInputAssembler(inputAssemblerInfo); #pragma endregion @@ -380,10 +368,14 @@ void ARBackground::render(cc::scene::Camera *camera, gfx::RenderPass *renderPass _pipelineState = _device->createPipelineState(pipelineInfo); + gfx::DrawInfo drawInfo; + drawInfo.indexCount = 6; + cmdBuffer->bindInputAssembler(_inputAssembler); cmdBuffer->bindPipelineState(_pipelineState); cmdBuffer->bindDescriptorSet(materialSet, _descriptorSet); - cmdBuffer->draw(_inputAssembler); + cmdBuffer->bindInputAssembler(_inputAssembler); + cmdBuffer->draw(drawInfo); } template diff --git a/native/tools/swig-config/gfx.i b/native/tools/swig-config/gfx.i index a0944e0ffd7..f9d11caf6b5 100644 --- a/native/tools/swig-config/gfx.i +++ b/native/tools/swig-config/gfx.i @@ -67,6 +67,8 @@ namespace cc { namespace gfx { %ignore CommandBuffer::updateBuffer; %ignore CommandBuffer::resolveTexture; %ignore CommandBuffer::copyBuffersToTexture; +%ignore CommandBuffer::drawIndirect; +%ignore CommandBuffer::drawIndexedIndirect; %rename(drawWithInfo) CommandBuffer::draw(const DrawInfo&); %ignore DescriptorSetLayout::getBindingIndices; @@ -183,7 +185,6 @@ namespace cc { namespace gfx { %attribute(cc::gfx::InputAssembler, cc::gfx::BufferList&, vertexBuffers, getVertexBuffers); %attribute(cc::gfx::InputAssembler, cc::gfx::AttributeList&, attributes, getAttributes); %attribute(cc::gfx::InputAssembler, cc::gfx::Buffer*, indexBuffer, getIndexBuffer); -%attribute(cc::gfx::InputAssembler, cc::gfx::Buffer*, indirectBuffer, getIndirectBuffer); %attribute(cc::gfx::InputAssembler, uint32_t, attributesHash, getAttributesHash); %attribute(cc::gfx::InputAssembler, cc::gfx::DrawInfo&, drawInfo, getDrawInfo, setDrawInfo);