import { GfxSamplerBinding , GfxBufferBinding , GfxBindingsDescriptor , GfxRenderPipelineDescriptor , GfxBindingLayoutDescriptor , GfxInputLayoutDescriptor , GfxVertexAttributeDescriptor , GfxProgram , GfxMegaStateDescriptor , GfxAttachmentState , GfxChannelBlendState , GfxSamplerDescriptor , GfxInputLayoutBufferDescriptor , GfxColor , GfxVertexBufferDescriptor , GfxIndexBufferDescriptor , GfxFormat , GfxBindingLayoutSamplerDescriptor } from './GfxPlatform' ; import { copyMegaState } from '../helpers/GfxMegaStateDescriptorHelpers' ; type EqualFunc < K > = ( a : K , b : K ) => boolean ; type CopyFunc < T > = ( a : T ) => T ; export function arrayCopy < T > ( a , copyFunc ) { const b = Array ( a . length ) ; for ( let i = 0 ; i < a . length ; i ++ ) b [ i ] = copyFunc ( a [ i ] ) ; return b ; } export function arrayEqual < T > ( a , b , e ) { if ( a . length !== b . length ) return false ; for ( let i = 0 ; i < a . length ; i ++ ) if ( ! e ( a [ i ] , b [ i ] ) ) return false ; return true ; } export function gfxSamplerBindingCopy ( a ) { const gfxSampler = a . gfxSampler , gfxTexture = a . gfxTexture , lateBinding = a . lateBinding ; return { gfxSampler , gfxTexture , lateBinding } ; } export function gfxSamplerBindingNew ( ) { return { gfxSampler : null , gfxTexture : null , lateBinding : null } ; } export function gfxBufferBindingCopy ( a ) { const buffer = a . buffer ; const wordCount = a . wordCount ; return { buffer , wordCount } ; } export function gfxBindingsDescriptorCopy ( a ) { const bindingLayout = a . bindingLayout ; const samplerBindings = arrayCopy ( a . samplerBindings , gfxSamplerBindingCopy ) ; const uniformBufferBindings = arrayCopy ( a . uniformBufferBindings , gfxBufferBindingCopy ) ; return { bindingLayout , samplerBindings , uniformBufferBindings } ; } function gfxBindingLayoutSamplerDescriptorCopy ( a ) { const dimension = a . dimension , formatKind = a . formatKind ; return { dimension , formatKind } ; } export function gfxBindingLayoutDescriptorCopy ( a ) { const numSamplers = a . numSamplers ; const numUniformBuffers = a . numUniformBuffers ; const samplerEntries = a . samplerEntries !== undefined ? arrayCopy ( a . samplerEntries ! , gfxBindingLayoutSamplerDescriptorCopy ) : undefined ; return { numSamplers , numUniformBuffers , samplerEntries } ; } export function gfxRenderPipelineDescriptorCopy ( a ) { const bindingLayouts = arrayCopy ( a . bindingLayouts , gfxBindingLayoutDescriptorCopy ) ; const inputLayout = a . inputLayout ; const program = a . program ; const topology = a . topology ; const megaStateDescriptor = copyMegaState ( a . megaStateDescriptor ) ; const colorAttachmentFormats = a . colorAttachmentFormats . slice ( ) ; const depthStencilAttachmentFormat = a . depthStencilAttachmentFormat ; const sampleCount = a . sampleCount ; return { bindingLayouts , inputLayout , megaStateDescriptor , program , topology , colorAttachmentFormats , depthStencilAttachmentFormat , sampleCount } ; } export function gfxVertexAttributeDescriptorCopy ( a ) { const location = a . location , format = a . format , bufferIndex = a . bufferIndex , bufferByteOffset = a . bufferByteOffset ; return { location , format , bufferIndex , bufferByteOffset } ; } export function gfxInputLayoutBufferDescriptorCopy ( a ) { if ( a !== null ) { const byteStride = a . byteStride , frequency = a . frequency ; return { byteStride , frequency } ; } else { return null ; } } export function gfxInputLayoutDescriptorCopy ( a ) { const vertexAttributeDescriptors = arrayCopy ( a . vertexAttributeDescriptors , gfxVertexAttributeDescriptorCopy ) ; const vertexBufferDescriptors = arrayCopy ( a . vertexBufferDescriptors , gfxInputLayoutBufferDescriptorCopy ) ; const indexBufferFormat = a . indexBufferFormat ; return { vertexAttributeDescriptors , vertexBufferDescriptors , indexBufferFormat } ; } function gfxBufferBindingEquals ( a , b ) { return a . buffer === b . buffer && a . wordCount === b . wordCount ; } function gfxSamplerBindingEquals ( a , b ) { if ( a === null ) return b === null ; if ( b === null ) return false ; return a . gfxSampler === b . gfxSampler && a . gfxTexture === b . gfxTexture ; } function gfxBindingLayoutSamplerDescriptorEqual ( a , b ) { return a . dimension === b . dimension && a . formatKind === b . formatKind ; } export function gfxBindingLayoutDescriptorEqual ( a , b ) { if ( a . numSamplers !== b . numSamplers ) return false ; if ( a . numUniformBuffers !== b . numUniformBuffers ) return false ; if ( ( a . samplerEntries === undefined ) !== ( b . samplerEntries === undefined ) ) return false ; if ( a . samplerEntries !== undefined && ! arrayEqual ( a . samplerEntries ! , b . samplerEntries ! , gfxBindingLayoutSamplerDescriptorEqual ) ) return false ; return true ; } export function gfxBindingsDescriptorEquals ( a , b ) { if ( a . samplerBindings . length !== b . samplerBindings . length ) return false ; if ( ! arrayEqual ( a . samplerBindings , b . samplerBindings , gfxSamplerBindingEquals ) ) return false ; if ( ! arrayEqual ( a . uniformBufferBindings , b . uniformBufferBindings , gfxBufferBindingEquals ) ) return false ; if ( ! gfxBindingLayoutEquals ( a . bindingLayout , b . bindingLayout ) ) return false ; return true ; } function gfxChannelBlendStateEquals ( a , b ) { return a . blendMode == b . blendMode && a . blendSrcFactor === b . blendSrcFactor && a . blendDstFactor === b . blendDstFactor ; } function gfxAttachmentStateEquals ( a , b ) { if ( ! gfxChannelBlendStateEquals ( a . rgbBlendState , b . rgbBlendState ) ) return false ; if ( ! gfxChannelBlendStateEquals ( a . alphaBlendState , b . alphaBlendState ) ) return false ; if ( a . channelWriteMask !== b . channelWriteMask ) return false ; return true ; } function gfxMegaStateDescriptorEquals ( a , b ) { if ( ! arrayEqual ( a . attachmentsState , b . attachmentsState , gfxAttachmentStateEquals ) ) return false ; if ( ! gfxColorEqual ( a . blendConstant , b . blendConstant ) ) return false ; return ( a . depthCompare === b . depthCompare && a . depthWrite === b . depthWrite && a . stencilCompare === b . stencilCompare && a . stencilWrite === b . stencilWrite && a . stencilPassOp === b . stencilPassOp && a . cullMode === b . cullMode && a . frontFace === b . frontFace && a . polygonOffset === b . polygonOffset ) ; } function gfxBindingLayoutEquals ( a , b ) { return a . numSamplers === b . numSamplers && a . numUniformBuffers === b . numUniformBuffers ; } function gfxProgramEquals ( a , b ) { return a . ResourceUniqueId === b . ResourceUniqueId ; } function gfxFormatEquals ( a , b ) { return a === b ; } export function gfxRenderPipelineDescriptorEquals ( a , b ) { if ( a . topology !== b . topology ) return false ; if ( a . inputLayout !== b . inputLayout ) return false ; if ( a . sampleCount !== b . sampleCount ) return false ; if ( ! gfxMegaStateDescriptorEquals ( a . megaStateDescriptor , b . megaStateDescriptor ) ) return false ; if ( ! gfxProgramEquals ( a . program , b . program ) ) return false ; if ( ! arrayEqual ( a . bindingLayouts , b . bindingLayouts , gfxBindingLayoutEquals ) ) return false ; if ( ! arrayEqual ( a . colorAttachmentFormats , b . colorAttachmentFormats , gfxFormatEquals ) ) return false ; if ( a . depthStencilAttachmentFormat !== b . depthStencilAttachmentFormat ) return false ; return true ; } export function gfxVertexAttributeDescriptorEquals ( a , b ) { return ( a . bufferIndex === b . bufferIndex && a . bufferByteOffset === b . bufferByteOffset && a . location === b . location && a . format === b . format ) ; } export function gfxInputLayoutBufferDescriptorEquals ( a , b ) { if ( a === null ) return b === null ; if ( b === null ) return false ; return ( a . byteStride === b . byteStride && a . frequency === b . frequency ) ; } export function gfxInputLayoutDescriptorEquals ( a , b ) { if ( a . indexBufferFormat !== b . indexBufferFormat ) return false ; if ( ! arrayEqual ( a . vertexBufferDescriptors , b . vertexBufferDescriptors , gfxInputLayoutBufferDescriptorEquals ) ) return false ; if ( ! arrayEqual ( a . vertexAttributeDescriptors , b . vertexAttributeDescriptors , gfxVertexAttributeDescriptorEquals ) ) return false ; return true ; } export function gfxSamplerDescriptorEquals ( a , b ) { return ( a . wrapS === b . wrapS && a . wrapT === b . wrapT && a . wrapQ === b . wrapQ && a . minFilter === b . minFilter && a . magFilter === b . magFilter && a . mipFilter === b . mipFilter && a . minLOD === b . minLOD && a . maxLOD === b . maxLOD && a . maxAnisotropy === b . maxAnisotropy && a . compareMode === b . compareMode ) ; } export function gfxColorEqual ( c0 , c1 ) { return c0 . r === c1 . r && c0 . g === c1 . g && c0 . b === c1 . b && c0 . a === c1 . a ; } export function gfxColorCopy ( dst , src ) { dst . r = src . r ; dst . g = src . g ; dst . b = src . b ; dst . a = src . a ; } export function assert ( b , message = "" ) { if ( ! b ) { console . error ( new Error ( ) . stack ) ; throw new Error ( `Assert fail: ${ message }` ) ; } } export function assertExists < T > ( v ) { if ( v !== undefined && v !== null ) return v ; else throw new Error ( "Missing object" ) ; } export function range ( start , count ) { const L = [ ] ; for ( let i = start ; i < start + count ; i ++ ) L . push ( i ) ; return L ; } export function leftPad ( S , spaces , ch = '0' ) { while ( S . length < spaces ) S = `${ ch }${ S }` ; return S ; } export function nArray < T > ( n , c ) { const d = new Array ( n ) ; for ( let i = 0 ; i < n ; i ++ ) d [ i ] = c ( ) ; return d ; } export function nullify < T > ( v ) { return v === undefined ? null : v ; } export function align ( n , multiple ) { const mask = ( multiple - 1 ) ; return ( n + mask ) & ~ mask ; } export function alignNonPowerOfTwo ( n , multiple ) { return ( ( ( n + multiple - 1 ) / multiple ) | 0 ) * multiple ; }