import ArrayBufferSlice from "../../ArrayBufferSlice" ; import { GfxBuffer , GfxDevice , GfxBufferUsage , GfxBufferFrequencyHint } from "../platform/GfxPlatform" ; import { assert , align } from "../platform/GfxPlatformUtil" ; export interface GfxCoalescedBuffer { buffer : GfxBuffer ; byteOffset : number ; byteCount : number ; } export function coalesceBuffer ( device , usage , datas ) { let dataLength = 0 ; for ( let i = 0 ; i < datas . length ; i ++ ) dataLength += datas [ i ] . byteLength ; const wordCount = align ( dataLength , 4 ) / 4 ; const buffer = device . createBuffer ( wordCount , usage , GfxBufferFrequencyHint . Static ) ; const coalescedBuffers = [ ] ; const combinedData = new Uint8Array ( wordCount * 4 ) ; let byteOffset = 0 ; for ( let i = 0 ; i < datas . length ; i ++ ) { const data = datas [ i ] ; combinedData . set ( data . createTypedArray ( Uint8Array ) , byteOffset ) ; coalescedBuffers . push ( { buffer , byteOffset , byteCount : data . byteLength } ) ; byteOffset += data . byteLength ; } device . uploadBufferData ( buffer , 0 , combinedData ) ; return coalescedBuffers ; } export interface GfxCoalescedBuffersCombo { vertexBuffers : GfxCoalescedBuffer [ ] ; indexBuffer : GfxCoalescedBuffer ; } export class GfxBufferCoalescerCombo { public coalescedBuffers : GfxCoalescedBuffersCombo [ ] = [ ] ; private vertexBuffer : GfxBuffer | null = null ; private indexBuffer : GfxBuffer | null = null ; constructor ( device , vertexDatas , indexDatas ) { assert ( vertexDatas . length === indexDatas . length ) ; if ( vertexDatas . length === 0 ) return ; const allVertexDatas = [ ] ; let maxSlice = 0 ; while ( true ) { let sliceHasBuffer = false ; for ( let i = 0 ; i < vertexDatas . length ; i ++ ) { if ( vertexDatas [ i ] [ maxSlice ] === undefined ) continue ; allVertexDatas . push ( vertexDatas [ i ] [ maxSlice ] ) ; sliceHasBuffer = true ; } if ( ! sliceHasBuffer ) break ; maxSlice ++ ; } const vertexCoalescedBuffers = coalesceBuffer ( device , GfxBufferUsage . Vertex , allVertexDatas ) ; const indexCoalescedBuffers = coalesceBuffer ( device , GfxBufferUsage . Index , indexDatas ) ; const coalescedBuffers = [ ] ; let z = 0 ; for ( let i = 0 ; i < vertexDatas . length ; i ++ ) { const vertexBuffers = [ vertexCoalescedBuffers [ z ++ ] ] ; const indexBuffer = indexCoalescedBuffers [ i ] ; coalescedBuffers . push ( { vertexBuffers , indexBuffer } ) ; } for ( let slice = 1 ; slice < maxSlice ; slice ++ ) { for ( let i = 0 ; i < vertexDatas . length ; i ++ ) { if ( vertexDatas [ i ] [ slice ] === undefined ) continue ; coalescedBuffers [ i ] . vertexBuffers . push ( vertexCoalescedBuffers [ z ++ ] ) ; } } this . coalescedBuffers = coalescedBuffers ; this . vertexBuffer = this . coalescedBuffers [ 0 ] . vertexBuffers [ 0 ] . buffer ; this . indexBuffer = this . coalescedBuffers [ 0 ] . indexBuffer . buffer ; } public destroy ( device ) { if ( this . vertexBuffer !== null ) device . destroyBuffer ( this . vertexBuffer ) ; if ( this . indexBuffer !== null ) device . destroyBuffer ( this . indexBuffer ) ; } } export function makeStaticDataBuffer ( device , usage , data ) { const gfxBuffer = device . createBuffer ( align ( data . byteLength , 4 ) / 4 , usage , GfxBufferFrequencyHint . Static ) ; device . uploadBufferData ( gfxBuffer , 0 , new Uint8Array ( data ) ) ; return gfxBuffer ; } export function makeStaticDataBufferFromSlice ( device , usage , data ) { const gfxBuffer = device . createBuffer ( align ( data . byteLength , 4 ) / 4 , usage , GfxBufferFrequencyHint . Static ) ; device . uploadBufferData ( gfxBuffer , 0 , data . createTypedArray ( Uint8Array ) ) ; return gfxBuffer ; }